PowerShellの配列サブ式について
[質問]
PowerShellで、次の3つの代入文の違いを教えてください。
$x = 1..4
$y = $(1..4)
$z = @(1..4)[回答] Gemini
PowerShellにおけるこれら3つの記述は、結果として同じ「1から4までの配列」を作成しているように見えますが、「式の評価方法」と「出力の保証」という点で重要な違いがあります。
結論から言うと、1..4 という範囲演算子がすでに配列を返すため、今回の例では最終的な中身に大きな差はありません。しかし、コマンドの実行結果を代入する際には挙動が変わります。
1. $x = 1..4 (直接代入)
最もシンプルで標準的な方法です。
- 挙動: 右辺の
1..4(範囲演算子)が評価され、それによって生成された[Object[]](配列)がそのまま$xに格納されます。 - 特徴: 余計なラッパーがないため、最も効率的です。
2. $y = $(1..4) (サブ式)
$() はサブ式(Subexpression)と呼ばれます。
- 挙動: 括弧内を「独立したスクリプト」として実行し、その結果を返します。
- 特徴: * 複数のステートメントを1行で実行し、その「最終的な出力」を代入したい場合に使います。
- 文字列の中で変数を展開したり、計算を行ったりする際によく使われます(例:
"結果は $($a + $b) です")。 - 注意点: 今回のケースでは、単に配列を配列として返すだけなので、あまり意味はありません。
3. $z = @(1..4) (配列サブ式)
@() は配列サブ式(Array subexpression)と呼ばれ、実務で最も重宝されます。
- 挙動: 中身が何であれ、結果を強制的に「配列」として返します。
- 特徴:
- 要素が 0個(null) や 1個 しかなくても、必ず配列(長さ0や1の配列)として扱われます。
- PowerShellの「要素が1つだと勝手にスカラー値(単一のデータ)に変換してしまう」という挙動を防ぎたい場合に非常に有効です。
違いの比較表
以下の表は、右辺が「1つしか結果を返さないコマンド(例: Get-Service で該当が1つ)」だった場合の違いをイメージするとわかりやすいです。
| 構文 | 形式 | 要素が1つの時の型 | 主な用途 |
|---|---|---|---|
$x = ... |
直接代入 | 単一オブジェクト | 通常の代入 |
$y = $(...) |
サブ式 | 単一オブジェクト | 文字列内での展開、複数処理の結合 |
$z = @(...) |
配列サブ式 | 常に配列 | 後続の処理で foreach や .Count を安全に使いたい時 |
結局どれを使うべき?
- 今回のように
1..4と決まっている場合は、シンプルに$x = 1..4で十分です。 - コマンドの結果(
Get-ChildItemなど)を変数に入れる場合は、結果が1つだったときにエラーにならないよう、$z = @(...)を使うのが「安全なプログラミング」の定石です。
Tips: >
$z = @(1..4)と書いた場合、厳密には「範囲演算子で作った配列」をさらに「配列サブ式」で包むことになるため、わずかにオーバーヘッドが発生しますが、現代のPCスペックでは無視できるレベルです。
次は、これらを使って「要素が1つの時の挙動の差」を実際に確認するコード例を作成しましょうか?