PowerShellを使用する上で、複数のデータを効率的に管理するための「配列」の扱いは避けて通れない重要なトピックです。
システム管理や自動化スクリプトにおいて、ファイル一覧やユーザー情報のリストを操作する際に配列は不可欠な役割を果たします。
本記事では、PowerShellにおける配列の基本的な宣言方法から、要素の追加や削除、そして大規模データを扱う際の高速化テクニックまでを詳しく解説します。
初心者の方から、より効率的なスクリプトを書きたい中級者の方まで、実務で役立つ知識を網羅的に整理しました。
PowerShellにおける配列の基本概念
PowerShellの配列は、複数の値を一つの変数にまとめて格納できる便利なデータ構造です。
配列に格納される各データは「要素」と呼ばれ、それぞれの要素には0から始まる「インデックス」番号が割り振られます。
PowerShellの配列は非常に柔軟であり、異なるデータ型(数値、文字列、オブジェクトなど)を一つの配列内に混在させることも可能です。
しかし、プログラムの堅牢性を高めるためには、特定の型のみを許可する型指定配列の利用も推奨されます。
標準的な配列は固定長として扱われるため、要素を頻繁に追加・削除する場合にはパフォーマンスに注意が必要です。
配列の宣言と初期化の方法
PowerShellで配列を作成する方法は、用途に応じていくつか存在します。
最も基本的な宣言方法
最も一般的な配列の作成方法は、カンマ区切りで値を指定し、変数に代入することです。
# カンマ区切りで配列を作成
$fruits = "apple", "banana", "orange"
また、明示的に配列であることを示すために @() 構文を使用することも一般的です。
# @() を使用した空の配列の宣言
$myArray = @()
# 値を指定して初期化
$colors = @("red", "green", "blue")
空の配列を初期化しておくことは、ループ処理で結果を格納する際にエラーを防ぐための定石です。
連続した数値の配列作成(範囲演算子)
特定の範囲の数値を配列にしたい場合は、範囲演算子 .. を活用すると非常に簡潔に記述できます。
# 1から10までの数値配列を作成
$numbers = 1..10
1
2
3
4
5
6
7
8
9
10
型を指定した配列の宣言
配列に格納するデータの型を制限したい場合は、変数名の前に型を指定します。
# 整数型のみを許容する配列
[int[]]$intNumbers = 1, 2, 3, 4, 5
型を指定することで、意図しないデータ型の混入を防ぎ、スクリプトの信頼性を向上させることができます。
配列要素へのアクセスと操作
作成した配列から特定のデータを取り出したり、値を変更したりする方法について解説します。
インデックスによる要素の取得
配列の要素にアクセスするには、角括弧 [] を使用してインデックス番号を指定します。
インデックスは「0」から始まる点に注意してください。
$apps = "Word", "Excel", "PowerPoint"
# 最初の要素を取得
$apps[0]
# 2番目の要素を取得
$apps[1]
Word
Excel
末尾からのアクセス(負のインデックス)
PowerShellでは、負の数を使用して配列の末尾から要素を指定することも可能です。
[-1] は最後の要素を指し、[-2] は最後から2番目の要素を指します。
$data = "A", "B", "C", "D"
$data[-1]
D
スライス(範囲指定)による取得
複数の要素を一度に取得したい場合は、スライス機能が便利です。
$letters = "a", "b", "c", "d", "e"
# インデックス1から3までを取得
$letters[1..3]
b
c
d
配列への要素の追加
PowerShellにおける標準的な配列は「固定サイズ」という性質を持っています。
そのため、要素を追加する際には内部的に新しい配列が再作成されていることを理解しておく必要があります。
+= 演算子による追加
最も手軽な方法は += 演算子を使用することです。
$myList = @("Home", "Work")
# 要素を追加
$myList += "Other"
一見すると単純な追加に見えますが、実際には元の配列に新しい要素を加えた「新しい配列」を生成し、元の変数に代入し直しています。
そのため、ループ内で数千回、数万回と += を繰り返すと、処理速度が著しく低下します。
配列からの要素の削除
標準の配列には Remove メソッドが存在しないため、特定の要素を除外した新しい配列を作成することで削除を実現します。
Where-Object を使用した削除(フィルタリング)
条件に一致する要素を取り除くには、Where-Object(エイリアス ?)を使用するのが一般的です。
$tags = "Red", "Blue", "Green", "Yellow"
# "Blue" 以外の要素で新しい配列を作成
$filteredTags = $tags | Where-Object { $_ -ne "Blue" }
「削除する」のではなく「必要なものだけを残す」という考え方がPowerShellの基本です。
特定のインデックスを削除する
インデックスを指定して削除したい場合は、スライスと演算子を組み合わせます。
$colors = "Red", "Blue", "Green", "Yellow"
# インデックス1(Blue)を除外して結合
$newColors = $colors[0] + $colors[2..3]
多次元配列とジャグ配列
複雑なデータ構造を扱うために、配列の中に配列を入れることも可能です。
多次元配列(行列)
すべての行の長さが等しい配列を多次元配列と呼びます。
# 2行3列の多次元配列を宣言
$matrix = New-Object 'object[,]' 2,3
$matrix[0,0] = "Row0-Col0"
$matrix[1,2] = "Row1-Col2"
ジャグ配列(配列の配列)
各要素がそれぞれ異なる長さの配列を持つ形式をジャグ配列と呼びます。
$jagged = @(
@("A", "B"),
@("C", "D", "E"),
@("F")
)
# アクセス方法
$jagged[1][2]
E
配列の検索とフィルタリング
配列内から特定の条件に合致する要素を効率的に見つける方法を紹介します。
-contains 演算子と -in 演算子
配列に特定の値が含まれているかを確認するには -contains または -in を使用します。
$servers = "SRV01", "SRV02", "SRV03"
# 配列に "SRV02" が含まれるか
$servers -contains "SRV02"
True
-match 演算子によるパターン検索
正規表現を使用して要素を検索し、一致した要素のみを抽出することもできます。
$files = "test.txt", "data.log", "config.xml", "run.exe"
# 拡張子が .log または .xml のものを抽出
$files -match "\.(log|xml)$"
data.log
config.xml
【重要】配列操作を高速化するコツ
大量のデータを扱う際、標準の配列(固定長配列)ではパフォーマンスの限界に直面することがあります。
ここでは、実務レベルで必須となる高速化の手法を解説します。
System.Collections.Generic.List[T] の活用
要素の追加・削除が頻繁に発生する場合は、.NETの List<T> クラスを使用するのが最も効果的です。
List<T> は可変長のリストであり、+= のように配列全体をコピーしないため、数万件のデータ処理でも圧倒的に高速です。
# 文字列型のListを生成
$list = New-Object System.Collections.Generic.List[string]
# Addメソッドで高速に追加
foreach ($i in 1..10000) {
$list.Add("Item $i")
}
大規模なログファイルの処理やActive Directoryのユーザー一覧取得など、データ件数が予測できない場合は最初からListを使用することを強く推奨します。
ArrayList の使用(古い手法との違い)
かつては System.Collections.ArrayList も使われていましたが、現在のPowerShell(特にPowerShell 7以降)では Generic.List の使用が推奨されています。
ArrayList はすべての要素を object 型として扱うため、型変換のオーバーヘッドが発生し、型安全性も低いためです。
パイプライン出力を配列で一括受け取り
ループ内で 1 つずつ配列に追加するのではなく、パイプラインの結果を直接変数に代入することで、内部的な最適化が行われます。
# 遅い例:ループ内で追加
$result = @()
foreach ($f in Get-ChildItem C:\Windows) {
$result += $f
}
# 速い例:直接代入
$result = Get-ChildItem C:\Windows
PowerShellのエンジンは、パイプラインの出力を一括で配列に格納する際に非常に効率的なメモリ割り当てを行います。
配列操作の便利なメソッドとテクニック
PowerShell 7以降で利用可能な機能を含め、知っておくと便利な操作をまとめました。
配列のソート(並び替え)
Sort-Object を使用することで、数値を昇順・降順に並び替えたり、オブジェクトの特定プロパティでソートしたりできます。
$nums = 5, 2, 8, 1
$nums | Sort-Object
重複の削除
Select-Object -Unique を使用すると、配列内の重複した値を取り除くことができます。
$duplicateArray = 1, 2, 2, 3, 3, 3
$uniqueArray = $duplicateArray | Select-Object -Unique
配列のカウント(要素数)
要素数を取得するには .Count プロパティを参照します。
$myArray = 1, 2, 3
$myArray.Count
なお、PowerShell 3.0以降では、変数が配列でなく単一のオブジェクトであっても .Count で 「1」 を返すため、エラーが起きにくい仕様になっています。
よくあるエラーとトラブルシューティング
配列操作で陥りやすいミスとその対策を整理します。
「コレクションは固定サイズです」エラー
$array.Add("item") を実行した際に「コレクションは固定サイズです」というエラーが表示されることがあります。
これは、前述した通り標準の配列が固定長であるために発生します。
このエラーを避けるには、+= を使うか、System.Collections.Generic.List を使用してください。
単一要素の配列が「配列」として扱われない問題
コマンドの結果が1件だけだった場合、PowerShellはそれを配列ではなく単一のオブジェクトとして変数に格納することがあります。
これにより、後続の処理で foreach ループが期待通りに動かないなどのトラブルが起こる場合があります。
これを確実に防ぐには、コマンド全体を @() で囲みます。
# 結果が1件でも強制的に配列として格納
$files = @(Get-ChildItem -Filter "only_one_file.txt")
このテクニックは、戻り値の数が動的に変わるスクリプトにおいて、極めて重要な「守り」の記述です。
まとめ
PowerShellにおける配列は、単純なデータのリスト保持から高度なデータ処理まで、あらゆる場面で利用される基盤機能です。
基本的な @() による宣言やインデックス操作をマスターした後は、用途に応じて適切なデータ構造を選択するスキルが求められます。
特に、大規模なデータを処理する際には += 演算子を避け、System.Collections.Generic.List[T] を活用することが、プロフェッショナルなスクリプト作成への近道です。
また、パイプラインや Where-Object を組み合わせたフィルタリングは、PowerShellらしい直感的かつ強力な記述を可能にします。
本記事で紹介したテクニックを活用し、メモリ効率が良く、実行速度の速い高品質な自動化スクリプトを実現してください。
配列を自在に操ることができれば、PowerShellによるシステム管理の効率は飛躍的に向上するはずです。
