如果我在powershell脚本中执行以下操作:
$range = 1..100
ForEach ($_ in $range){
if ($_ % 7 -ne 0 ) { continue; }
Write-Host "$($_) is a multiple of 7"
}
我得到了预期的输出:
7 is a multiple of 7
14 is a multiple of 7
21 is a multiple of 7
28 is a multiple of 7
35 is a multiple of 7
42 is a multiple of 7
49 is a multiple of 7
56 is a multiple of 7
63 is a multiple of 7
70 is a multiple of 7
77 is a multiple of 7
84 is a multiple of 7
91 is a multiple of 7
98 is a multiple of 7
但是,如果我使用管道和ForEach-Object
,则继续似乎会突破管道循环。
1..100 | ForEach-Object {
if ($_ % 7 -ne 0 ) { continue; }
Write-Host "$($_) is a multiple of 7"
}
我的问题是,我是否可以在继续使用ForEach-Object时获得类似行为,所以我不必分解我的管道?
答案 0 :(得分:144)
只需使用return
代替continue
即可。此return
从脚本块返回,该块由ForEach-Object
在特定迭代中调用,因此,它模拟循环中的continue
。
1..100 | ForEach-Object {
if ($_ % 7 -ne 0 ) { return }
Write-Host "$($_) is a multiple of 7"
}
在重构时要牢记这一点。有时,人们希望将foreach
语句块转换为带有ForEach-Object
cmdlet的管道(它甚至还有别名foreach
,这有助于简化此转换并使错误变得容易)。所有continue
都应替换为return
。
P.S。不幸的是,在break
中模拟ForEach-Object
并不容易。
答案 1 :(得分:17)
因为For-Each
对象是cmdlet而不是循环,并且continue / break不适用于它。
例如,如果你有:
$b = 1,2,3
foreach($a in $b){
$a | foreach { if($_ -eq 2) {continue;} else {write-host $_} }
write-host "after"
}
您将获得输出:
1
after
3
after
这是因为continue应用于外部foreach循环而不是foreach-object cmdlet。没有循环,最外层,因此给你的印象就像休息一样。
那么你如何继续像行为一样?一种方式是在哪里 - 对象:
1..100 | ?{ $_ % 7 -eq 0} | %{write-host $_ is a mutliple of 7}
答案 2 :(得分:3)
另一种选择是一种黑客攻击,但是你可以将你的块包装在一个执行一次的循环中,这种方式继续将产生预期的效果:
1..100 | ForEach-Object {
for($cont=$true;$cont;$cont=$false){
if ($_ % 7 -ne 0 ) { continue; }
Write-Host "$($_) is a multiple of 7"
}
}
答案 3 :(得分:0)
一个简单的else语句使它按原样工作
1..100 | ForEach-Object {
if ($_ % 7 -ne 0 ) {
#do nothing
} else {
Write-Host "$($_) is a multiple of 7"
}
}
或在单个管道中
1..100 | ForEach-Object { if ($_ % 7 -ne 0 ) {} else {Write-Host "$($_) is a multiple of 7"}}
但是更优雅的解决方案是反转测试并仅为成功生成输出
1..100 | ForEach-Object {if ($_ % 7 -eq 0 ) {Write-Host "$($_) is a multiple of 7"}}