web-dev-qa-db-ja.com

Powershellが1つのアイテムを含む文字列配列を黙って文字列に変換する理由

名前に「og」が含まれるC:\内のフォルダーを検索する次のPowershellスクリプトを考えてみます。

 PS C:\>(ls |%{$ _。Name} |?{$ _。Contains( "og")})
 PerfLogs 
プログラムファイル
 setup.log 

検索を絞り込んで、1つのアイテムのみを取得します。

 PS C:\>(ls |%{$ _。Name} |?{$ _。Contains( "Prog")})
プログラムファイル

奇妙なことに、最初の操作はarrayを生成しますが、2番目の操作(意味的に同じ操作であるため、同じタイプの結果を生成するはずです)はstring。これは、次の結果で確認できます。

 PS C:\>(ls |%{$ _。Name} |?{$ _。Contains( "og")})。Length 
 3 
 PS C: \>(ls |%{$ _。Name} |?{$ _。Contains( "Prog")})。Length 
 13 

「Prog」に一致するフォルダよりも「og」に一致するフォルダが少ないため、これは非常に苛立たしい場合があります。

明らかに、PowerShellは暗黙的に単一項目配列を単一オブジェクトに「アンボックス」し、長さ1の配列を取得することはありません。パイプラインを介して送られる結果をカウントするたびに、私が確認する必要があるようです ' m配列を扱うかどうか。

これを防ぐにはどうすればよいですか?これにどう対処しますか?

39
cheesus

明らかに、PowerShellは暗黙的に単一アイテム配列を単一オブジェクトに「ボックス化解除」します。

Andゼロの結果は_$null_になります。

これを防ぐにはどうすればよいですか?

できません。

これにどう対処しますか?

配列コンストラクター(@(...))を使用して、コレクション(おそらく0または1つの要素)を強制的に返します。

_$res = @(ls | %{$_.Name} | ?{$_.Contains("Prog")})
_
60
Richard

これら2つの結果の違いに注意してください。

PS C:\> ConvertTo-Json -InputObject @(1)
[
    1
]
PS C:\> @(1)|ConvertTo-Json
1
PS C:\>

ポイントは、「ボックス化解除」がパイプ操作によって行われていることです。 ConvertTo-Jsonは、パイプではなくInputObjectを使用する場合でも、オブジェクトを配列として認識します。

4
Larry Young

これはPowerShell v3で解決されています。

http://blogs.Microsoft.co.il/blogs/scriptfanatic/archive/2012/03/19/Counting-objects-in-PowerShell-3.0.aspx

補足として、ワイルドカードを使用して名前に何かが含まれているかどうかを確認できます。

PS> ls *og*
2
Shay Levy