我可以从内循环引用外循环中的迭代 $_ 值吗?
Can I refer to the iterated $_ value in an outer loop from the inner loop?
出于演示目的,我有一个 JSON 文档,其中列出了大洲和每个大洲的一些国家:
$json = ConvertFrom-Json '[{"Continent" : "Europe","Countries" : ["UK","France","Germany"]},
{"Continent" : "Africa","Countries" : ["Mali","Malawi","Nigeria"]}]'
如果我想获得其中所有国家/地区的列表,我可以通过管道连接到 foreach
cmdlet 两次,在 PowerShell 的一行中完成此操作:
$json | foreach {$_.Countries} | foreach {$_ | Select @{Name="Country";Expression={$_}}}
Country
------- UK France Germany Mali Malawi Nigeria
一切都很正常。但是,如果我也想 Select 每个国家/地区的大陆,那么我需要一个 multi-statement 脚本块:
$json | foreach {
$Continent = $_.Continent
$_.Countries | foreach {
$_ | Select-Object @{Name="Continent";Expression={$Continent}},@{Name="Country";Expression={$_}}
}
}
Continent Country
--------- -------
Europe UK
Europe France
Europe Germany
Africa Mali
Africa Malawi
Africa Nigeria
我喜欢 PowerShell 的简洁性,所以在第二个示例中,我对需要将迭代大陆存储在变量中这一事实感到有些泄气。我想知道的是,我可以让它变得更好吗?我可以让它更简洁吗?有没有办法从对 Select-Object
?
的调用中引用外循环中的迭代值
仅此而已,基本上只是想了解更多有关 PowerShell 及其功能的信息。
我认为不可能得到 "outer" $_
。而且,就算可以,我觉得也不是什么好主意
您可以使用 Get-Variable -Scope 1
在 Powershell 中(递归地)引用父作用域,其中 1 是直接父作用域,但这在嵌套的 ForEach-Object
调用中似乎不起作用。有关详细信息,请参阅 about_Scopes。
在我看来,尽管为了可读性而编写代码通常更好。
如果您被多语句块打扰的主要原因是它在多行中,您可以用 ;
分隔语句以使它们保持在同一行。
$json | foreach { $Continent = $_.Continent ; $_.Countries | foreach { $_ | Select-Object @{Name="Continent";Expression={$Continent}},@{Name="Country";Expression={$_}} }}
就个人而言,我更喜欢分解的。
您不能直接访问外部 $_
的值,但您可以使用 param
:
捕获它的值
param($x=$_)
从技术上讲,这将使您能够在一行中完成所有操作:
$json | foreach { param($x=$_) $_.Countries | foreach { $_ | Select-Object @{Name="Continent";Expression={$x.Continent}},@{Name="Country";Expression={$_}}}}
您还可以通过使用一些标准别名(即 %
代表 foreach
和 select
代表 Select-Object
)来减少代码的大小:
$json | % { param($x=$_) $_.Countries | % { $_ | select @{Name="Continent";Expression={$x.Continent}},@{Name="Country";Expression={$_}}}}
但我只建议这样做是为了在控制台中快速运行。将打包且无法实现的代码投入生产简直就是罪恶。 ;)
出于演示目的,我有一个 JSON 文档,其中列出了大洲和每个大洲的一些国家:
$json = ConvertFrom-Json '[{"Continent" : "Europe","Countries" : ["UK","France","Germany"]},
{"Continent" : "Africa","Countries" : ["Mali","Malawi","Nigeria"]}]'
如果我想获得其中所有国家/地区的列表,我可以通过管道连接到 foreach
cmdlet 两次,在 PowerShell 的一行中完成此操作:
$json | foreach {$_.Countries} | foreach {$_ | Select @{Name="Country";Expression={$_}}}
Country ------- UK France Germany Mali Malawi Nigeria
一切都很正常。但是,如果我也想 Select 每个国家/地区的大陆,那么我需要一个 multi-statement 脚本块:
$json | foreach {
$Continent = $_.Continent
$_.Countries | foreach {
$_ | Select-Object @{Name="Continent";Expression={$Continent}},@{Name="Country";Expression={$_}}
}
}
Continent Country --------- ------- Europe UK Europe France Europe Germany Africa Mali Africa Malawi Africa Nigeria
我喜欢 PowerShell 的简洁性,所以在第二个示例中,我对需要将迭代大陆存储在变量中这一事实感到有些泄气。我想知道的是,我可以让它变得更好吗?我可以让它更简洁吗?有没有办法从对 Select-Object
?
仅此而已,基本上只是想了解更多有关 PowerShell 及其功能的信息。
我认为不可能得到 "outer" $_
。而且,就算可以,我觉得也不是什么好主意
您可以使用 Get-Variable -Scope 1
在 Powershell 中(递归地)引用父作用域,其中 1 是直接父作用域,但这在嵌套的 ForEach-Object
调用中似乎不起作用。有关详细信息,请参阅 about_Scopes。
在我看来,尽管为了可读性而编写代码通常更好。
如果您被多语句块打扰的主要原因是它在多行中,您可以用 ;
分隔语句以使它们保持在同一行。
$json | foreach { $Continent = $_.Continent ; $_.Countries | foreach { $_ | Select-Object @{Name="Continent";Expression={$Continent}},@{Name="Country";Expression={$_}} }}
就个人而言,我更喜欢分解的。
您不能直接访问外部 $_
的值,但您可以使用 param
:
param($x=$_)
从技术上讲,这将使您能够在一行中完成所有操作:
$json | foreach { param($x=$_) $_.Countries | foreach { $_ | Select-Object @{Name="Continent";Expression={$x.Continent}},@{Name="Country";Expression={$_}}}}
您还可以通过使用一些标准别名(即 %
代表 foreach
和 select
代表 Select-Object
)来减少代码的大小:
$json | % { param($x=$_) $_.Countries | % { $_ | select @{Name="Continent";Expression={$x.Continent}},@{Name="Country";Expression={$_}}}}
但我只建议这样做是为了在控制台中快速运行。将打包且无法实现的代码投入生产简直就是罪恶。 ;)