为什么在Foreach-Object中继续表现得像break?

Jus*_*ing 112 powershell foreach

如果我在powershell脚本中执行以下操作:

$range = 1..100
ForEach ($_ in $range) {
    if ($_ % 7 -ne 0 ) { continue; }
    Write-Host "$($_) is a multiple of 7"
}
Run Code Online (Sandbox Code Playgroud)

我得到了预期的输出:

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
Run Code Online (Sandbox Code Playgroud)

但是,如果我使用管道ForEach-Object,继续似乎打破了管道循环.

1..100 | ForEach-Object {
    if ($_ % 7 -ne 0 ) { continue; }
    Write-Host "$($_) is a multiple of 7"
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,我是否可以在继续使用ForEach-Object时获得类似行为,所以我不必分解我的管道?

Rom*_*min 148

只需使用return而不是continue.这return将从ForEach-Object特定迭代调用的脚本块返回,因此,它模拟continue循环.

1..100 | ForEach-Object {
    if ($_ % 7 -ne 0 ) { return }
    Write-Host "$($_) is a multiple of 7"
}
Run Code Online (Sandbox Code Playgroud)

重构时要牢记这一点.有时候人们想要将一个foreach语句块转换为一个带有ForEach-Objectcmdlet 的管道(它甚至还有一个别名foreach,有助于简化这种转换并使错误变得容易).所有continue都应该被替换return.

PS不幸的是,它不是那么容易模仿breakForEach-Object.

  • @ Richard Hauer这样的`continue`会破坏整个脚本,而不仅仅是使用它的`ForEach-Object`. (4认同)
  • 从OP所说的显然`continue`可以用来模拟`ForEach-Object`中的`break` :) (2认同)

man*_*lds 17

因为For-Eachobject是cmdlet而不是循环,并且continue/break不适用于它.

例如,如果您有:

$b = 1,2,3

foreach($a in $b) {

    $a | foreach { if ($_ -eq 2) {continue;} else {Write-Host $_} }

    Write-Host  "after"
}
Run Code Online (Sandbox Code Playgroud)

你会得到输出:

1
after
3
after
Run Code Online (Sandbox Code Playgroud)

这是因为continue应用于外部foreach循环而不是foreach-object cmdlet.没有循环,最外层,因此给你的印象就像休息一样.

那么你如何继续像行为一样?一种方式是在哪里 - 对象:

1..100 | ?{ $_ % 7  -eq 0} | %{Write-Host $_ is a multiple of 7}
Run Code Online (Sandbox Code Playgroud)

  • @manojlds也许他认为你的单线解决方案"难以阅读",至少对我来说完全相反.管道工作方式非常强大和清晰,对于简单的事情来说是正确的方法.在shell中编写代码而不利用它是没有意义的. (3认同)