Wenn ich folgendes in einem Powershell-Skript mache:
$range = 1..100
ForEach ($_ in $range){
if ($_ % 7 -ne 0 ) { continue; }
Write-Host "$($_) is a multiple of 7"
}
Ich bekomme die erwartete Ausgabe von:
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
Wenn ich jedoch eine Pipeline und ForEach-Object
verwende, scheint fortzufahren aus der Pipeline-Schleife auszubrechen.
1..100 | ForEach-Object {
if ($_ % 7 -ne 0 ) { continue; }
Write-Host "$($_) is a multiple of 7"
}
Meine Frage lautet: Kann ich mich weiterhin mit ForEach-Object fortbewegen, sodass ich meine Pipeline nicht auflösen muss?
Verwenden Sie einfach die return
anstelle der continue
. Diese return
wird aus dem Skriptblock zurückgegeben, der bei einer bestimmten Iteration von ForEach-Object
aufgerufen wird, und simuliert somit die continue
in einer Schleife.
1..100 | ForEach-Object {
if ($_ % 7 -ne 0 ) { return }
Write-Host "$($_) is a multiple of 7"
}
Dies ist ein Problem, das beim Refactoring zu beachten ist. Manchmal möchte man einen foreach
-Anweisungsblock mit einem ForEach-Object
-Cmdlet in eine Pipeline konvertieren (er hat sogar den Aliasnamen foreach
, der die Konvertierung vereinfacht und auch Fehler vereinfacht. Alle continue
sollten durch return
ersetzt werden.
P.S. Leider ist es nicht so einfach, break
in ForEach-Object
zu simulieren.
Da das For-Each
-Objekt ein Cmdlet und keine Schleife und ein Weitersuchlauf ist, gilt dies nicht für das Objekt.
Zum Beispiel, wenn Sie:
$b = 1,2,3
foreach($a in $b){
$a | foreach { if($_ -eq 2) {continue;} else {write-Host $_} }
write-Host "after"
}
sie werden ausgegeben als:
1
after
3
after
Der Grund ist, dass die Weitergabe auf die äußere Foreach-Schleife und nicht auf das Foreach-Object-Cmdlet angewendet wird. In Abwesenheit einer Schleife, äußerster Ebene, so dass Sie einen Eindruck davon bekommen, dass er wie ein Bruch wirkt.
Wie kommst du dann weiter? Ein Weg ist wo-Objekt des Kurses:
1..100 | ?{ $_ % 7 -eq 0} | %{write-Host $_ is a mutliple of 7}
Eine andere Alternative ist eine Art Hack, aber Sie können Ihren Block in eine Schleife einwickeln, die einmal ausgeführt wird. Auf diese Weise wird fortfahren die gewünschte Wirkung erzielt:
1..100 | ForEach-Object {
for($cont=$true;$cont;$cont=$false){
if ($_ % 7 -ne 0 ) { continue; }
Write-Host "$($_) is a multiple of 7"
}
}
Eine einfache else-Anweisung macht es so, wie es ist
1..100 | ForEach-Object {
if ($_ % 7 -ne 0 ) {
#do nothing
} else {
Write-Host "$($_) is a multiple of 7"
}
}
oder in einer einzigen Pipeline
1..100 | ForEach-Object { if ($_ % 7 -ne 0 ) {} else {Write-Host "$($_) is a multiple of 7"}}
eine elegantere Lösung ist jedoch, den Test zu invertieren und nur für Ihre Erfolge zu generieren
1..100 | ForEach-Object {if ($_ % 7 -eq 0 ) {Write-Host "$($_) is a multiple of 7"}}