以下两个代码段为什么产生不同的输出?
Connection
使用以下json执行代码段:
Get-Content -Raw "test.json" | ConvertFrom-Json | %{
Write-Output "MessageType: $($_.Messagetype)"
}
# this time make sure Get-Content and ConvertFrom-Json are evaluated completely, before the foreach
(Get-Content -Raw "test.json" | ConvertFrom-Json) | %{
Write-Output "MessageType: $($_.Messagetype)"
}
第一个脚本产生
[
{
"MessageType": "A"
},
{
"MessageType": "B"
}
]
第二个是预期的
MessageType: A B
因此基本上,对于第一个代码片段,foreach会得到一个元素,该元素是一个包含2个元素的数组,而在第二个代码片段中,foreach会为每个元素调用。
我不明白为什么强制评估会完全改变这里的行为。
答案 0 :(得分:2)
ConvertFrom-Json
与大多数其他cmdlet不同,它将数组作为单个对象 输出,而不是通过管道一一发送对象。 [1 ]
因此,在您的 first 命令的%
(ForEach-Object
)脚本块中,$_
是 entire数组,可扩展字符串("..."
)内的字符串会默认为由空格分隔的其元素列表。
相比之下,在(...)
中加上命令会将其转换为表达式,并且在管道中使用表达式会隐式导致枚举表达式的结果,导致对象被一一发送。
因此,您的 second 命令的%
(ForEach-Object
)脚本块被两次调用,其中$_
绑定到< em>单个对象。
简化示例:
# Sample JSON that is an array comprising 2 objects.
$json = '[
{
"MessageType": "A"
},
{
"MessageType": "B"
}
]'
# -> 1, because ConvertFrom-Json sent the array as a whole
$json | ConvertFrom-Json | Measure-Object | % Count
# -> 2, because using (...) resulted in enumeration
($json | ConvertFrom-Json) | Measure-Object | % Count
[1]此异常行为在this GitHub问题中进行了讨论。