If I do the following in a powershell script:
$range = 1..100
ForEach ($_ in $range){
if ($_ % 7 -ne 0 ) { continue; }
Write-Host "$($_) is a multiple of 7"
}
I get the expected output of:
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
However, if I use a pipeline and ForEach-Object
, continue seems to break out of the pipeline loop.
1..100 | ForEach-Object {
if ($_ % 7 -ne 0 ) { continue; }
Write-Host "$($_) is a multiple of 7"
}
My questions is, can I get a continue like behavior while still doing ForEach-Object, so I don't have to breakup my pipeline?
Another alternative is kind of a hack, but you can wrap your block in a loop that will execute once, that way continue will have the desired effect:
A simple else statement makes it work as is
or in a single pipeline
but a more elegant solution is to invert your test and generate output for only your successes
Simply use the
return
instead of thecontinue
. Thisreturn
returns from the script block which is invoked byForEach-Object
on a particular iteration, thus, it simulates thecontinue
in a loop.This is a gotcha to be kept in mind on refactoring. Sometimes one wants to convert a
foreach
statement block into a pipeline with aForEach-Object
cmdlet (it even has the aliasforeach
that helps to make this conversion easy and make mistakes easy, too). Allcontinue
should be replaced withreturn
.P.S. Unfortunately, it is not that easy to simulate
break
inForEach-Object
.Because
For-Each
object is a cmdlet and not a loop and continue / break do not apply to it.For example, if you have:
you will get output as:
It is because the continue gets applied to the outer foreach loop and not the foreach-object cmdlet. In absence of a loop, outermost level, hence giving you an impression of it acting like break.
So how do you get continue like behaviour? One way is where-object ofcourse: