コンテンツにスキップ

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つの時の挙動の差」を実際に確認するコード例を作成しましょうか?