72068


PowerShellの配列は`@("hoge", "fuga")`のように要素入りで初期化できます。

その挙動について、  
`@("hoge"; "fu" + "ga")`と記述すると配列の要素は`["hoge", "fuga"]`になりますが  
`@("hoge", "fu" + "ga")`と記述すると配列の要素は`["hoge", "fu", "ga"]`に分割されてしまいます。

`@(1 - 2; 1 + 2)`では`[-1, 3]`を得られますが、  
`@(1 - 2, 1 + 2)`では各要素がObjectとして扱われ、下記のエラーが発生します。

> [System.Object[]] に 'op_Subtraction' という名前のメソッドが含まれないため、メソッドの呼び出しに失敗しました。

なぜ`,`と`;`の区切り文字で挙動が変わるのでしょうか。

**検証コード**

[code]

    "1: 想定通り" 
    $ar = @()
    $ar += "hoge" 
    $ar += ("fu" + "ga")
    $ar += 1 + 2
    $ar += "pi" + "yo" 
    $ar
    
    "`n2: ';'で分けるとうまくいく" 
    @(
        "hoge";
        ("fu" + "ga");
        1 + 2;
        "pi" + "yo" 
    )
    
    "`n3: ','で分けるとうまくいかない" 
    @(
        "hoge",
        ("fu" + "ga"),
        1 + 2,       # 分割されてしまう！
        "pi" + "yo"  # 分割されてしまう！
    )
    
    "`n4: 1項目なら計算してもうまくいく" 
    @(1 - 2)
    "`n5: 数字だけでも','だと引き算がエラー" 
    @(1 - 2, 3, 4)
    "`n6: 上記と同様にエラー" 
    @(1 - 2, 3; 4)
    "`n7: エラーじゃない！" 
    @(1 - 2; 3, 4)
    
[/code]

**検証結果**

[code]

    1: 想定通り
    hoge
    fuga
    3
    piyo
    
    2: ';'で分けるとうまくいく
    hoge
    fuga
    3
    piyo
    
    3: ','で分けるとうまくいかない
    hoge
    fuga
    1
    2
    pi
    yo
    
    4: 1項目なら計算してもうまくいく
    -1
    
    5: 数字だけでも','だと引き算がエラー
    [System.Object[]] に 'op_Subtraction' という名前のメソッドが含まれないため、メソッドの呼び出しに失敗しました。
    発生場所 C:\Users\payaneco\Scripts\test.ps1:28 文字:1
    + @(1 - 2, 3, 4)  # エラー
    + ~~~~~~~~~~~~~~
        + CategoryInfo          : InvalidOperation: (op_Subtraction:String) []、RuntimeException
        + FullyQualifiedErrorId : MethodNotFound
    
    6: 上記と同様にエラー
    [System.Object[]] に 'op_Subtraction' という名前のメソッドが含まれないため、メソッドの呼び出しに失敗しました。
    発生場所 C:\Users\payaneco\Scripts\test.ps1:30 文字:3
    + @(1 - 2, 3; 4)
    +   ~~~~~~~~
        + CategoryInfo          : InvalidOperation: (op_Subtraction:String) []、RuntimeException
        + FullyQualifiedErrorId : MethodNotFound
    
    4
    
    7: エラーじゃない！
    -1
    3
    4
    
[/code]

なお質問にあたって[配列について知りたいことのすべて](https://docs.microsoft.com/ja-
jp/powershell/scripting/learn/deep-dives/everything-about-
arrays?view=powershell-7.1)を参照しましたが、知りたいことを見つけることができませんでした。


CC BY-SA 4.0
2020-11-19T03:25:28.013
72053
2020-11-22T02:59:00.360
9820
question
powershell
配列宣言時に各要素の区切り文字を変えると動作が異なるのは何故か


そもそも`,`演算子が配列を構築します。`1,2,3`で３項目の配列が作られますし、`,7`で１項目だけの配列です。その上で、この`,`演算子の優先順位がかなり高いです。（正確には演算子ではなさそうです）

> `@("hoge", "fu" + "ga")`と記述すると配列の要素は`["hoge", "fu", "ga"]`に分割されてしまいます。
[code]

    @("hoge", "fu" + "ga")
      ↓
    @(@("hoge", "fu") + "ga")
      ↓
    @("hoge", "fu") + @("ga")
      ↓
    @("hoge", "fu", "ga")
    
[/code]

先に配列が構築され、そこに[`+`演算子で配列に項目追加](https://docs.microsoft.com/en-
us/powershell/module/microsoft.powershell.core/about/about_arithmetic_operators?view=powershell-7.1#adding-
and-multiplying-non-numeric-types)が行われます。

> `@(1 - 2, 1 + 2)`では各要素がObjectとして扱われ、下記のエラーが発生します。
[code]

    @(1 - 2, 1 + 2)
      ↓
    @(1 - @(2, 1) + 2)
    
[/code]

Objectとなるわけではなく `1 - @(2, 1)` つまり `数値 － 配列` が実行できずにエラーです。

なお、`;`はステートメントを終了させるキーワードで優先順位はとても低いです。そのため期待通りの解釈が行われます。

* * *

おまけ

>
[code]

>     @(
>         "hoge";
>         ("fu" + "ga");
>         1 + 2;
>         "pi" + "yo"
>     )
>  
[/code]

シェルスクリプトらしく **行末** も`;`と同様にステートメントの終了を表すため

[code]

    @(
        "hoge"
        "fu" + "ga"
        1 + 2
        "pi" + "yo" 
    )
    
[/code]

でも期待通りの配列になります。


CC BY-SA 4.0
2020-11-19T09:33:37.997
72068
2020-11-22T02:59:00.360
2020-11-22T02:59:00.360
4236
4236
72053
answer