Powershell の配列でハマったのでメモ。
- 配列を作る。
こんな感じで , (カンマ)演算子を使うことで配列が生成できます。
ps> $a = 1, 2, 3 ps> Write-Host "Len:" $a.Length " Type:" $a.GetType().Name Len: 3 Type: Object[]
- 要素 1 の配列を作る。
上記だと、要素 2 以上の配列は作成できますが、要素 1 の配列が作成できません。
要素 1 の配列を作るには、@(~) を使用しますps> $a = @(1) ps> Write-Host "Len:" $a.Length " Type:" $a.GetType().Name # 確認 Len: 1 Type: Object[]
また、@() とすれば要素 0 の配列を作れます。
ps> $a = @() ps> Write-Host "Len:" $a.Length " Type:" $a.GetType().Name # 確認 Len: 0 Type: Object[]
- 配列の配列(ジャグ配列)を作る。
括弧で括ってやれば、そこを一つの配列として構成してくれます。
ps> $a = (1, 2), 3, (4, 5, 6) ps> Write-Host "Len:" $a.Length " Type:" $a.GetType().Name # 確認 Len: 3 Type: Object[] ps> $a | % {Write-Host "Len:" $_.Length " Type:" $_.GetType().Name} # 確認 Len: 2 Type: Object[] Len: 1 Type: Int32 Len: 3 Type: Object[]
- 要素 1 の配列に、配列を入れたい。
今回のメインテーマ。以下はダメです。
# @() を重ねる ps> $a = @(@(1, 2)) ps> Write-Host "Len:" $a.Length " Type:" $a.GetType().Name # 確認 Len: 2 Type: Object[] # 配列を作ってから、@() で括る ps> $b = 1, 2; $a = @($b) ps> Write-Host "Len:" $a.Length " Type:" $a.GetType().Name # 確認 Len: 2 Type: Object[] # 空配列を作ってから、配列を足す ps> $a = @(); $a += 1,2 ps> Write-Host "Len:" $a.Length " Type:" $a.GetType().Name # 確認 Len: 2 Type: Object[]
しかし、これはできる!
# 一旦、要素 1 の配列を作ってから、その中身を入れ替える ps> $a = @(1); $a[0] = 1, 2 ps> Write-Host "Len:" $a.Length " Type:" $a.GetType().Name # 確認 Len: 1 Type: Object[] ps> $a | % {Write-Host "Len:" $_.Length " Type:" $_.GetType().Name} # 確認 Len: 2 Type: Object[]
でも、かっこ悪い(汗 ・・・ので Powershell v3 以降は , (カンマ)単項演算子で対処できる模様です。
ps> $a = ,(1, 2) ps> Write-Host "Len:" $a.Length " Type:" $a.GetType().Name # 確認 Len: 1 Type: Object[] ps> $a | % {Write-Host "Len:" $_.Length " Type:" $_.GetType().Name} # 確認 Len: 2 Type: Object[]
括弧を省略すると、意図しないところが配列になる可能性があるので気をつけるようにします。(冷静に考えたら当然そうなる…)
ps> $a = ,1, 2 ps> Write-Host "Len:" $a.Length " Type:" $a.GetType().Name # 確認 Len: 2 Type: Object[] ps> $a | % {Write-Host "Len:" $_.Length " Type:" $_.GetType().Name} # 確認 Len: 1 Type: Object[] Len: 1 Type: Int32
- 要素 1 に配列が入れられると、何の役に立つか?
これが何の役に立つかと言うと、配列の引数を一つだけとるコンストラクタを呼びたいときなどに使えます。
たとえば、string(char[]) を呼びたいとき、配列を素直に渡すと失敗します。ps> $a = [Char]0x41, [Char]0x42 ps> New-Object string $a AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
これは、string(char, int) が呼ばれた結果で、Powershell は配列を展開してから引数に渡してくれるのでした(汗 #余計なお世話
このため、配列の引数を一つだけ取るコンストラクタを呼びたい場合は、この展開を考慮して「配列の配列」で渡してやる必要があるようです。
ps> $a = ,([Char]0x41, [Char]0x42) ps> New-Object string $a AB
また、これをワンライナーで書こうとした場合、以下のように書くと失敗します。
ps> New-Object string ,([Char]0x41, [Char]0x42) New-Object : パラメーター 'ComObject' で必要とされる型 'System.String' に 'System.Object[]' を変換できません。指定されたメソッドはサポートされていません。 発生場所 行:1 文字:12 + New-Object string ,([Char]0x41, [Char]0x42) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidArgument: (:) [New-Object]、ParameterBindingException + FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Commands.NewObjectCommand
エラーメッセージの言っていることがよく分かりませんが(ぇ)、前後に括弧を入れてやることで対策できます。
ps> New-Object string (,([Char]0x41, [Char]0x42)) AB ps> $a = [Char]0x41, [Char]0x42 ps> New-Object string (,$a) AB
[PS1] String と Char 配列の相互変換など | オールトの雲
[…] [PS1] Powershell の配列 […]
Link | 2015年9月10日 23:36