为什么 Powershell 会默默地将包含一个项目的字符串数组转换为字符串

为什么 Powershell 会默默地将包含一个项目的字符串数组转换为字符串

考虑以下 Powershell 脚本,它在 C:\ 中搜索名称中带有“og”的文件夹:

PS C:\> (ls | %{$_.Name} | ?{$_.Contains("og")})
性能日志
程序文件
安装日志

现在我缩小搜索范围,只得到一个项目:

PS C:\> (ls | %{$_.Name} | ?{$_.Contains("Prog")})
程序文件

奇怪的是,第一个操作产生了一个大批而第二个操作(在我看来,语义上是相同的操作,所以应该产生相同类型的结果)产生了一个细绳。这可以从以下结果中看出:

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

这可能非常令人恼火,因为显然与“og”匹配的文件夹比与“Prog”匹配的文件夹少。

显然,PowerShell 隐式地将单项数组“拆箱”为单个对象,并且我们永远不会得到长度为 1 的数组。似乎每次我想计算通过管道传来的结果时,我都必须检查我是否正在处理数组。

我该如何防止这种情况发生?你如何处理这个问题?

答案1

显然,PowerShell 隐式地将单个项目数组“拆箱”为单个对象,

零项结果为$null

我怎样才能防止这种情况发生?

你不能。

你如何处理这个问题?

使用数组构造函数(@(...))强制返回集合(可能包含零个或一个元素):

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

答案2

请注意这两个结果之间的区别:

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

重点是“拆箱”是通过管道操作完成的。如果我们使用 InputObject 而不是管道,ConvertTo-Json 仍会将对象视为数组。

答案3

解决这个问题的另一种方法是明确地将变量类型设置为数组,如下所示:

[array]$res = (ls | %{$_.Name} | ?{$_.Contains("og")})

答案4

这对我有用,但我必须在一个新变量中声明结果,否则 PowerShell 只是将数组分解为单个对象……最令人沮丧。

感谢微软没有考虑 JSON 的用例......插入沸腾的讽刺

$result = ConvertTo-Json -InputObject @($body) -compress

相关内容