考虑以下 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