我正在尝试对一些 REST API 响应进行排序并从中提取数据,结果发现 this helpful回答如何在最后得到一个哈希表。
$res= (Invoke-RestMethod @commonParams -uri "foo" -Method GET -FollowRelLink) | ForEach-Object { $_ } | Select-Object -Property id, filename | ForEach-Object -begin {$h=@{}} -process {$h[$_.filename] = $_.id} -end {$h}
太好了,所以我想通过去掉开始/过程/结束 block 来缩短它,如下所示:
$res = (Invoke-RestMethod @commonParams -uri "foo" -Method GET -FollowRelLink) | ForEach-Object { $_ } | Select-Object -Property id, filename | ForEach-Object { $h=@{}; $h[$_.filename] = $_.id; $h }
一切都好,我现在应该能够使用方括号通过其键值引用每个项目,但这不起作用,只能通过点表示法引用。
所以我去搜索并找到了this answer ,事实证明这是正确的:
$res.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
但是,即使从通用哈希表构造函数更改为使用 .Add()
方法也没有帮助:
$res = (Invoke-RestMethod @commonParams -uri "foo" -Method GET -FollowRelLink) | ForEach-Object { $_ } | Select-Object -Property id, filename | ForEach-Object { $h=@{}; $h.add($_.filename, $_.id); $h }
$res.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
我将流程 block 添加回:
$res = (Invoke-RestMethod @commonParams -uri "$foo" -Method GET -FollowRelLink) | ForEach-Object { $_ } | Select-Object -Property id, filename | ForEach-Object -begin {$h=@{}} -process {$h[$_.filename] = $_.id} -end {$h}
$res.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Hashtable System.Object
一切都按预期进行。
所以我想知道,如果可能的话,当我使用进程 block 而不是在管道中创建“假”多行函数时到底发生了什么?
如果有人关心的话,我实际上最终通过使用 here 中的 Group-Object
完全避免了上述问题。 .
最佳答案
ForEach-Object
模拟如何script blocks工作于pipeline 。第一个和最后一个片段按预期工作并返回哈希表的原因是 -Begin
和 -End
而不是因为 -Process
执行默认情况下,并且是强制参数。如果您不使用 -Begin
,您只需为每个输入对象创建并输出一个新的哈希表。
- 使用
ForEach-Object
0..10 | ForEach-Object -Begin {
"executes only once, before the first input object is processed"
} -Process {
"processes each input object: $_"
} -End {
"executes only once, after the last input object is processed"
}
- 使用脚本 block
0..10 | & {
begin {
"executes only once, before the first input object is processed"
}
process {
"processes each input object: $_"
}
end {
"executes only once, after the last input object is processed"
}
}
about_Functions_Advanced_Methods解释这些 block 是如何工作的。
您的代码也可以简化为:
$h = @{}
Invoke-RestMethod @commonParams -uri "foo" -Method GET -FollowRelLink |
Write-Output |
ForEach-Object { $h[$_.filename] = $_.id }
或者使用Group-Object -AsHashTable
正如您已经发现的:
$h = Invoke-RestMethod @commonParams -uri "foo" -Method GET -FollowRelLink |
Write-Output |
Group-Object FileName -AsHashTable
如果已经枚举了 Invoke-RestMethod
的输出,则在这种情况下可能不需要 Write-Output
。
关于powershell - 为什么进程 block 正确返回哈希表,而不是哈希表数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75467328/