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

che*_*sus 51 powershell pipe

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

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

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

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

奇怪的是,第一个操作产生一个array,而第二个操作(恕我直言,语义上是相同的操作,所以它应该产生相同类型的结果)产生一个string。这可以在以下结果中看到:

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

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

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

我怎样才能防止这种情况发生?你如何处理这个问题?

Ric*_*ard 72

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

零项结果到$null.

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

你不能。

你如何处理这个问题?

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

$res = @(ls | %{$_.Name} | ?{$_.Contains("Prog")})
Run Code Online (Sandbox Code Playgroud)

  • `ConvertTo-Json -InputObject @(1)` 输出 `[1]`。您需要将数组显式包装到 `@(...)` 中 (4认同)
  • 不确定你可以“强制”它。`@(1) | ConvertTo-Json` 仍然返回 `1` 而不是 `[1]`。 (3认同)

小智 12

请注意这两个结果之间的差异:

PS C:\> ConvertTo-Json -InputObject @(1)
[
    1
]
PS C:\> @(1)|ConvertTo-Json
1
PS C:\>
Run Code Online (Sandbox Code Playgroud)

关键是“拆箱”是由管道操作完成的。如果我们使用 InputObject 而不是管道,ConvertTo-Json 仍然将对象视为数组。