PowerShellの配列

これまたプログラミング言語では避けて通ることのできないもの、配列だ。配列はデータが列にならんでいるもののことをいう。ほかのプログラミング言語を経験したことのある方であればすんなり入ることができるだろう。

配列をつくるには

PowerShellにおいて配列を用意することが実は最も簡単なのではないかと思われる。なお、ここでいう配列とはデータ型がObjectである配列のことだ。PowerShellにおいては特殊な演算子を使用して配列をつくる。

$a = @(1, 2, 3)

これが基本的な配列のつくりかただ。アットマークが付いているところがPowerShellらしくて気持ち悪い。上記のコードにより、変数aには要素数3のオブジェクト配列が1次元で作成される。この場合、配列のサイズは固定になる。足すことはできるが要素を削ることはできない。

これよりもさらに簡単な方法がある。次は「,」演算子を利用する。これまた「-replace」演算子の説明において紹介したのだが、気付いているだろうか?カンマ記号を使って並べるだけで配列を生成してしまうのだ。

1, 2, 3  # => [1, 2, 3]

なお、文字列であれば前述した「-split」演算子を利用することで容易に1次配列を得ることができる。

"1,2,3,4,5" -split "," # => [1, 2, 3, 4, 5]

数値でかつ連続している配列の場合はさらに簡単で、「..」演算子を使う。これは範囲演算子と呼ばれており「1..10」などと直感的に利用することができる。

1..10  # => [1,2,3,4,5,6,7,8,9,10]

配列の操作

よく使用する操作としては、各要素へのアクセスであったり要素の追加がほとんどだろう。各要素へアクセスするにはよくあるプログラミング言語と同様に変数名に続いて [] を利用してインデックス番号を指定すればよい。このとき、インデックスは0からはじまる。

$a = 1..10
$a[3]  # => 2

インデックス番号にマイナスの値を与えた場合は配列の最後から計算される。

$a = 1..10
$a[-3]  # => 8

さらに、インデックスには数値の配列を指定することができる。たとえば次の例では要素が3番目と9番目を指定しているため、それらを要素にもつ配列が返される。

$a = 1..10
$a[3, 9]  # => [4, 10]

配列が指定できるということは範囲演算子を使用して配列中の特定の範囲の要素を取り出すことができる。これも配列として返される。

$a = 1..10
$a[3..6]  # => [4, 5, 6, 7]

配列同士を結合するには前述したとおり「+」演算子を、繰り返し結合するには「*」演算子を使うことができる。つまり要素の追加をしたい場合は配列を左側において「+」を使用すればよいことがわかる。

$a += @(4, 5, 6)  # => $a + @(4,5,6)
$a += 7  # => $a + 7

多次元配列

PowerShellでも一次元配列に限らず多次元の配列を作成することができるのだが、どうしても自動的に一次元のオブジェクト配列をつくろうとしてしまう。よって多次元配列をつくるときにはそれほど柔軟な作成をすることはできない。基本的な作成をすれば次のようになるだろう。

$a = @(@(1,2,3), @(4,5,6))
$a[1]  # => [4, 5, 6]

少しカジュアルな方法としてカンマ演算子による作成ができる。しかし明確にこの要素が配列だと示さなければ容易に一次配列を返してくるので注意が必要だ。

$a = 1, (1..10)
$a[1]  # => [1,2,3,4,5,6,7,8,9,10]

.Net Frameworkを利用した操作

PowerShellの配列はSystem.Arrayオブジェクトである。そのため常に固定サイズとなる。可能なことはClearメソッドにより配列の要素を0にするか、配列の要素数をLengthプロパティで確認するくらいだろう。変数名に続いてドット記号を入力し、タブキーにより補完しようとすると利用できるプロパティやメソッドが表示される。その中にRemoveやAdd、Insertなど、いかにも利用できそうなメソッドを見つけることができる。しかしこれはPowerShellが独自に拡張しているだけであり、実際にはどれも固定サイズ配列であるため動作しない。すべてエラーになる。よって、要素の追加は「+」演算子などで行い、要素の除去は特殊な比較演算子を利用して新たに配列を作成することで実現するのだ。

では、「+」や「*」演算子はなぜ配列要素数や配列そのものを変更できているのだろうか?答えは簡単で、元の配列をまったく操作していないからだ。同じ変数へ再代入していることからもわかるとおり、別の配列オブジェクトが作成されているのだ。だから固定サイズでまったく変更ができないにもかかわらずサイズが変更されている。配列要素数が小さいデータであれば問題にならないかもしれないが、巨大なデータを扱う場合には配列が一から再作成されてしまうということを頭の片隅に置いておく必要がある。

もしもC#に慣れ親しんでいて、あるいはJavaなどの言語に慣れ親しんでいてPowerShellの配列のパフォーマンスの悪さにうんざりしたとしたら、.NetFramworkにあるArrayListやListクラスを利用するとよいだろう。ただ、その時でもうっかりするとPowerShellはオブジェクトの一次配列を返してくることがあるので注意してほしい。

配列に有効な演算子

PowerShellの配列には有効な演算子が配列そのものの操作以外にも存在している。たとえば「-eq」「-ne」「-lt」「-lg」「-gt」「-ge」といったものだ。これらは比較演算子のところでご紹介したわけだが、配列のときには挙動が変化することもお話しした。配列が相手のときはフィルターとして利用することができる。

たとえば、次のコードは5以上となる要素をもつ配列を返す。

1..10 -ge 10 # => [5, 6, 7, 8, 9, 10]

要素に1から10までを持つ配列のうち、5以上のものがフィルタされた結果だからだ。非常に直感的だが、この挙動がnullかどうかを比較したいときに困る要因となる。

他に変わった比較演算子として「-in」がある。これは配列を右側にとる演算子で、指定された値が配列中に含まれているかをチェックする。否定形の「-notin」もあるので用途に応じて使い分けしよう。

3 -in -3..2  # => False

この「-in」演算子だが、バージョン3以降で追加された演算子であるため、バージョン2までは.NetFrameworkを活用して配列のもつ「Contains」メソッドを使用すると同じ結果を得ることができる。

(-3..2).Contains(1)  # => True

ただ、演算子でも同様なものが存在している。「-contains」演算子は「-in」とは逆で左側の配列に右側で与えられた要素が存在するかをチェックする。

1..10 -contains 3  # => True

英語のとおり読むことができれば演算子としては「-contains」と「-in」のどちらでもよいだろう。古いWindows環境で動作させるのであれば「-contains」のほうが無難だ。

results matching ""

    No results matching ""