Powershellが1つのアイテムを持つ文字列配列を文字列にサイレントに変換するのはなぜですか


33

次のPowershellスクリプトを検討してください。このスクリプトは、名前に「og」が含まれるC:\内のフォルダーを検索します。

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

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

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

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

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

これは、「Prog」に一致するフォルダよりも「og」に一致するフォルダが少ないため、非常にいらいらする可能性があります。

明らかに、PowerShellは暗黙的に単一項目配列を単一オブジェクトに「アンボックス化」し、長さ1の配列を取得することはありません。 m配列を扱うかどうか。

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


StackOverflowのからこれらが役立つことがあります。stackoverflow.com/questions/1827862/...の stackoverflow.com/questions/1390782/...をあなたにパイピングされていない場合は$_.Contains、その後、%{,,$_.Name}作品...
ボブ

回答:


56

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

そして、結果はゼロ$nullです。

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

できません。

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

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

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

ありがとう、これは完璧です!評判が15になったらすぐに投票します。
モニカ傷つけcheesus SOストップ

2
「強制」できるかどうかはわかりません。@(1) | ConvertTo-Jsonそれでもの1代わりに戻ります[1]
マーク

@Marc:ConvertTo-Jsonコレクションを返すことはありません。入力全体を読み取り、単一の文字列に変換します。入力オブジェクトを個別に変換する場合は、それぞれを個別に処理する必要があります。
リチャード

1
@Richard、あなたは誤解していると思います:私と他の多くの人は、基本的にオブジェクト全体(つまりコレクション)をシリアル化することを望んでいます(外部永続性のためなど)。コレクション内の各オブジェクトを個別に処理する必要はありません。ConvertTo-Jsonは、空の配列/コレクションであるにもかかわらず、ConvertFrom-Jsonが元のオブジェクトを返す文字列を返す必要があります。
マーク

@Marcこの質問のポイントは、単一の要素配列をその要素として扱うことを避けることです(これは、後続のPSH変更による問題ではありません。質問の日付に注意してください)。あなたは完全に異なるケース(コレクションを単一のオブジェクトにすること)について話しているので、私は誤解しています。
リチャード

2

これはPowerShell v3で解決されました。

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

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

PS> ls *og*

6
シェイ、答えにまだコメントできませんが、あなたの声明は真実ではありません。PowerShellはまだ要素を囲みますが、既に述べたように、単一のアイテムに「カウント」値が与えられています。ただし、単一アイテムの結果は未開封のままです。上記の例をPS 3に対してテストして、結果を確認できます。
-Tohuw

1
PS 5でも動作は同じです
。– MEMark

うん、デフはまだ存在しています
ジェームズワイズマン

1
この動作はPS 6.0.1でも同じです
spuder

2

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

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

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.