powershell - sort - ¿Por qué continúa comportándose como una ruptura en un Foreach-Object?
powershell foreach-object (3)
Como For-Each
object es un cmdlet y no un bucle y continue / break no se aplica a él.
Por ejemplo, si tiene:
$b = 1,2,3
foreach($a in $b){
$a | foreach { if($_ -eq 2) {continue;} else {write-host $_} }
write-host "after"
}
obtendrás salida como:
1
after
3
after
Es porque el continuar se aplica al bucle foreach externo y no al cmdlet foreach-object. En ausencia de un bucle, el nivel más externo, por lo tanto, le da una impresión de que actúa como un descanso.
Entonces, ¿cómo consigues continuar como un comportamiento? Una forma es donde, por supuesto, el objeto:
1..100 | ?{ $_ % 7 -eq 0} | %{write-host $_ is a mutliple of 7}
Si hago lo siguiente en un script de powershell:
$range = 1..100
ForEach ($_ in $range){
if ($_ % 7 -ne 0 ) { continue; }
Write-Host "$($_) is a multiple of 7"
}
Obtengo el resultado esperado de:
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
Sin embargo, si uso una canalización y ForEach-Object
, continue parece salir del bucle de la tubería.
1..100 | ForEach-Object {
if ($_ % 7 -ne 0 ) { continue; }
Write-Host "$($_) is a multiple of 7"
}
Mi pregunta es, ¿puedo seguir comportándome de la misma manera mientras sigo haciendo ForEach-Object, para no tener que romper mi pipeline?
Otra alternativa es una especie de truco, pero puedes envolver tu bloque en un bucle que se ejecutará una vez, de esa manera continuará tendrá el efecto deseado:
1..100 | ForEach-Object {
for($cont=$true;$cont;$cont=$false){
if ($_ % 7 -ne 0 ) { continue; }
Write-Host "$($_) is a multiple of 7"
}
}
Simplemente use la return
lugar de continue
. Este return
regresa del bloque de script invocado por ForEach-Object
en una iteración particular, por lo tanto, simula el continue
en un bucle.
1..100 | ForEach-Object {
if ($_ % 7 -ne 0 ) { return }
Write-Host "$($_) is a multiple of 7"
}
Esto es algo que debe tenerse en cuenta en la refactorización. A veces uno quiere convertir un bloque de instrucciones foreach
en una canalización con un cmdlet ForEach-Object
(incluso tiene el alias foreach
que ayuda a facilitar esta conversión y también a cometer errores). Todo continue
debe ser reemplazado con return
.
PD Desafortunadamente, no es tan fácil simular una break
en ForEach-Object
.