まずPowerShellのHelloWorldを実行してみます。Windowsのコマンドプロンプト(Cmd.exe)やLinuxのbashなど、従来のコマンドライン環境ではechoコマンドを使用しましたが、PowerShellでそのようなものは不要です。
PS U:\> "Hello World"
Hello World
PS U:\>
Hello World
PS U:\>
PowerShellでは「表れたデータは行き着く先がなければ画面に出力される」という性質があります。上記の場合、二重引用符""で囲んでいる部分は文字列のデータとみなされます。この文字列を変数に代入するような命令はしていませんし、パイプラインに流す命令もないので、行き着く先がなくなり、画面に出力されたというわけです。
これと同じ理由で、次の場合も画面に出力されます。
PS U:\> 1 # 整数
1
PS U:\> 2.1 # 実数
2.1
PS U:\> 6.3/3 # 式
2.1
PS U:\>
1
PS U:\> 2.1 # 実数
2.1
PS U:\> 6.3/3 # 式
2.1
PS U:\>
式を与えるとそのまま計算されます。exprコマンドやそれに相当するコマンドレットを書く必要はありません。
変数の代入は次のようにします。代入するときも$が必要です。数値を直接書いた場合と同じように、変数だけそのまま書いた場合も、やはり画面に出力されます。
PS U:\Work> $x = 2.0
PS U:\Work> $x
2
PS U:\Work>
PS U:\Work> $x
2
PS U:\Work>
■オブジェクト指向の側面
従来のCUIとPowerShellの最も大きな違いは、PowerShellにはオブジェクト指向プログラミングの要素が入っていることだと思います。先ほどまで「文字列のデータ」などと書いてきましたが、PowerShellの文字列は単なるデータではなく文字列型のオブジェクトです。整数や実数もそれぞれオブジェクトです。
それでは単なるデータとオブジェクトでは何が違うのでしょうか。オブジェクトには、自分自身に関する情報であるプロパティや、自分自身と関係する何らかの処理であるメソッドが結びついているのが、単なるデータとの違いです。プロパティやメソッドなど、オブジェクトに結びついているものを、そのオブジェクトの「メンバー」と呼びます。
オブジェクトには「型」があり、その型によって使用できるプロパティやメソッドが異なってきます。つまり、文字列型(String型)のオブジェクトはString型のプロパティやメソッドが、整数には整数型(int型)のメソッドやプロパティが結びついています。
■プロパティの例
では、そのプロパティを実際に見てみます。
PS U:\Work> ("abcdefg").Length
7
PS U:\Work>
7
PS U:\Work>
文字列、つまりString型オブジェクトである"abcdefg"を( )で囲み .Length をつけたところ、7と出力されました。この「7」は、文字列の長さを表しています。
既に何度も書きましたが、PowerShellでは文字列もオブジェクトです。そして、自分自身(文字列)の長さを表す「プロパティ」をもっています。上記の書き方をすると、String型オブジェクトのLengthプロパティを取得できるのです。
従来のCUIや、オブジェクト指向でないプログラミング言語では、文字列の長さを計算するコマンドや関数を呼び出して文字列長を取得していました。PowerShellは、文字列自身が持っているプロパティを参照することで、文字列長を取得するのです。
■メソッドの例
さて、今度はメソッドの呼び出しをしてみます。先ほども書きましたが、メソッドとはオブジェクトに結びついている処理であり、オブジェクト自身を使って何か行うものです。
String型には多くのメソッドがついていますが、その1つに、文字列の一部が置換された文字列を新たに生成するものがあります。とりあえずまたコマンドを実行してみましょう。
PS U:\Work> ("abcdefg").Replace("cde","01234")
ab01234fg
PS U:\Work>
ab01234fg
PS U:\Work>
文字列中の"cde"の部分が"01234"に置き換わった文字列が出力されました。
メソッドの概念の説明とはあまり関係がないのですが、上の結果は、"abcdefg"の一部が置換されたのではありません。"abcdefg"の一部が置き換わった文字列が、新たに作られたのです。この違いは変数にしてみると分かりやすいかと思います。
PS U:\Work> $text = "abcdefg"
PS U:\Work> $text.Replace("cde","01234")
ab01234fg
PS U:\Work> $text
abcdefg
PS U:\Work>
PS U:\Work> $text.Replace("cde","01234")
ab01234fg
PS U:\Work> $text
abcdefg
PS U:\Work>
文字列型のオブジェクトが格納された変数である $text のReplace()メソッドを呼び出し、"ab01234fg"が出力されました。しかし、その後で $text を出力すると、元の文字列がそのまま表示されました。つまり、$textに格納された文字列は全く変わっていないのです。Replace()メソッドに限らず、String型のオブジェクトを代入した変数は、別のオブジェクトを代入しない限りは、ずっと同じ文字列が入ったままです。このことは頭に入れておくと役に立つことがあるかも知れません。
■型の違い
話は変わりますが、Get-Itemコマンドレットにパスを指定すると、ファイル(FileInfo型)やフォルダー(DirectoryInfo型)のオブジェクトを取得できます。
PS U:\> Get-Item U:\Style.css
ディレクトリ: U:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2010/07/24 8:16 3296 Style.css
PS U:\>
ディレクトリ: U:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 2010/07/24 8:16 3296 Style.css
PS U:\>
ここで、「Mode」など表の列名になっているのはFileInfo型オブジェクトのプロパティです。「Length」というプロパティもあります。文字列のLengthプロパティは文字列長を表していましたが、ファイルのLengthプロパティはそのファイルのバイト数です。
文字列の長さもファイルの長さも言葉の上ではどちらも「長さ」なので上記の動作は理にかなっています。しかし、機能の上でこの2つは全く違うものです。オブジェクト指向では、同名のプロパティであっても、結びついているオブジェクトによって適切に動作が切り替わるようになっています。
FileInfoのLengthもプロパティには違いないので、( )で囲んで .Lengthをつけるとその値だけ取得できます。
PS U:\> (Get-Item U:\Style.css).Length
3296
PS U:\>
3296
PS U:\>
■おまけ
文字列を直接書いた場合は、メンバーを呼び出すのに( )が不要です。
PS U:\> "abcdefg".Length
7
PS U:\>
7
PS U:\>
文字列に限らず、メソッドやプロパティによって取得したオブジェクトを使う場合も( )が不要です。
PS U:\> "abcdefg".Replace("cde","01234").Length
9
PS U:\> "abcdefg".Replace("cde","01234") # 比較用に実行
ab01234fg
PS U:\>
9
PS U:\> "abcdefg".Replace("cde","01234") # 比較用に実行
ab01234fg
PS U:\>

