概要
ここでは、配列について説明します。
PowerShell では、2つのコマンドをパイプラインで繋ぐと、 オブジェクトの配列として入出力の受け渡しが行われます。
配列
PowerShell には , を使う方法と @ を使う方法、 2種類の配列の作り方があります。 (あと、整数限定で .. 演算子というのもあります。)
, 演算子
まず、複数のオブジェクトを , を使って並べると、 並べたオブジェクトを要素とする配列ができます。 また、配列の要素には [] を使ってアクセスします(インデックスは 0 から始まる)。
> $a = 1,2,3,4 > $a 1 2 3 4 > $a[0] # ↓ PowerShell の配列は 0 ベース 1 > $a.Length 4
,1 というように、単項演算子的にも使えます。 (長さ1の配列になる。)
> $a = ,1 > $a.Length 1 > $a[0] 1
この , 演算子はかなり結合順位が高いので注意。
> 1, 1+1, 1 # ↓ 要するに (1, 1) + (1, 1) 1 1 1 1
@()
もう1つは @ を使う方法で、 @(1, 2, 3) というように、@ に続けて () を書くと配列が作れます。 こちらの場合、区切り文字は ; (要するに、コマンドの区切り)も使えます。 あと、@() で空(長さ0)の配列も作れます。
> @(1; 2; 3) 1 2 3 > $a = @() > $a.GetType().Name Object[] > $a.Length 0
この記法では、複数のコマンドや式の出力・計算結果を繋いで配列にすることもできます。 (この場合、区切り文字は ; でないと駄目。)
> $a = @(pwd; 1 + 1) > $a[0] Path ---- C:\Users\Public > $a[1] 2
.. 演算子
あと、整数に限れば、1..3 (1, 2, 3 と同じ意味)というように、 .. を使って一定範囲の連続した数値列を作ることができます。
> 1..3
1
2
3
結合の優先順位が , 演算子より下なようで、 「1..3, 5」と言うような書き方はエラーになります。 (@ を使って、@(1..3; 5) という書き方なら OK。)
> 1..3,5 "System.Object[]" を "System.Int32" に変換できません。 > @(1..3; 5) 1 2 3 5
.. を使った配列と , を使った配列を併用したければ、 後述する配列結合の + 演算子を使う手もあります。
> 1..3 + 5, 7
1
2
3
5
7
末尾からのアクセス
配列のインデックスに負の数 −i を指定すると、 配列の末尾から i 番目の要素にアクセスできます。
> $a = 1,2,3 > $a[-1] 3 > $a[-2] 2 > $a[-3] 1
範囲外へのアクセス
配列に対して、範囲外にアクセスした場合、 読み出しなら null 値を返すだけで、 書き込みはエラーになります。
> $a = @() > $a[0] # ↓ null を返すだけ > $a[0] = 1 インデックス '0' が範囲外のため、配列の代入が失敗しました。
配列の連結
配列は + 演算子で連結することができます。
> $a = 1,2 > $b = 3,4 > $c = $a + $b > $c.Length 4 > $c 1 2 3 4
- が配列の結合なので、 += は要素の追加になります。
> $a = 1,2,3 > $a += 10 > $a 1 2 3 10
, 演算子でも連結されたように見えたりしますが、 実際には多次元配列になります。
> $a = 1,2 > $b = 3,4 > $c = $a, $b > $c 1 2 3 4 > $c[0] 1 2 > $c[1] 3 4 > $c.Length 2
部分取得
以下のような記法で、 配列の一部分を抜き出すことができます。
> $a = 1,2,3,4,5,6 > $a[1,3,5] 2 4 6 > $a[0..2] 1 2 3 > $a[0..2 + 4] 1 2 3 5
条件演算子
-contains 演算子で、配列の中に要素が含まれているかどうかを調べることができます。
> $a = 1,3,5 > $a -contains 1 True > $a -contains 2 False
また、 配列に対して、-eq や -lt などの比較演算子を使うことで、 特定条件を満たす要素だけを抜き出すことができます。
> $a = 1,2,3,9,8,7,4,5,6 > $a -lt 5 1 2 3 4 > $a -gt 5 9 8 7 6
複数の変数の同時代入
$a, $b, $c = 1, 2, 3 というように、 左辺も , で繋ぐことで、複数の変数に同時に値を代入することができます。 左右で要素の数が違う場合、 最後の1変数が配列になったり、 足りない分が null 値になったりします。
> $a, $b, $c = 1,2,3,4,5 > $a 1 > $b 2 > $c 3 4 5 > $a, $b, $c = 1,2 > $a 1 > $b 2 > $c
連想配列
@() で普通の配列を作るのに対して、 @{} で連想配列を作れます。 (型は System.Collections.Hashtable になります。)
(連想配列は、 Perl でいうところのハッシュ、 C++ の map、 C# の Hashtable や Dictionary のことで、 a["test"] = 1 とかいうように、 数字以外のインデックスを持てる配列です。)
$a = @{} という風にして空の連想配列を作って、 後から要素を作ることもできますし、 $a = @{x = 1} というように初期化のときに要素を作ることもできます。
要素へのアクセスには2通りの方法があります。 1つは、配列らしく、$a["x"] と書く記法で、 もう1つは $a.x というようにあたかもメンバー変数にアクセスするかのような記法です。
> $a = @{} > $a.x = 1 > $a.x 1
> $a = @{x = 1; y = 2; z = 3} > $a.x 1 > $a.y 2 > $a.z 3
> $a["x"] = 1 > $a["x"] 1
ちなみに、連想配列のキーは、別に文字列である必要はありません。
> $a[1.234] = 1 > $a[ [DateTime]::Now ] = 2 > $a[1024] = 3 > $a[ [int] ] = 4
すごく気持ち悪いですけど、 . を使う方でも任意の型のキーを参照できます。
> $a[[int]] = 2 > $a.[int] 2 > $b = [DateTime]::Now > $a[$b] = 6 > $a.$b 6 > $a[2] = 3 > $a.(1 + 1) 3 > $a.x = 9 > $a."x" 9