about_Pipeline_Chain_Operators
Descripción breve
Describe las canalizaciones de encadenamiento con los &&
operadores y ||
en PowerShell.
Descripción larga
A partir de PowerShell 7, PowerShell implementa los &&
operadores y ||
para encadenar canalizaciones condicionalmente. Estos operadores se conocen en PowerShell como operadores de cadena de canalización y son similares a las listas AND-OR en shells POSIX como bash, zsh y sh, así como símbolos de procesamiento condicional en el Shell de comandos de Windows (cmd.exe).
El operador &&
ejecuta la canalización derecha, si la canalización izquierda se ha realizado correctamente. Por el contario, el operador ||
ejecuta la canalización derecha, si la canalización izquierda no se ha realizado correctamente.
Estos operadores usan las variables $?
y $LASTEXITCODE
para determinar si se produjo un error en una canalización. Esto le permite usarlas con comandos nativos y no solo con cmdlets o funciones. Por ejemplo:
# Create an SSH key pair - if successful copy the public key to clipboard
ssh-keygen -t rsa -b 2048 && Get-Content -Raw ~\.ssh\id_rsa.pub | clip
Ejemplos
Dos comandos correctos
Write-Output 'First' && Write-Output 'Second'
First
Second
Se produce un error en el primer comando, lo que provoca que no se ejecute el segundo
Write-Error 'Bad' && Write-Output 'Second'
Write-Error: Bad
El primer comando se realiza correctamente, por lo que el segundo comando no se ejecuta
Write-Output 'First' || Write-Output 'Second'
First
Se produce un error en el primer comando, por lo que se ejecuta el segundo comando.
Write-Error 'Bad' || Write-Output 'Second'
Write-Error: Bad
Second
El éxito de la canalización se define mediante el valor de la $?
variable , que PowerShell establece automáticamente después de ejecutar una canalización en función de su estado de ejecución.
Esto significa que los operadores de cadena de canalización tienen la equivalencia siguiente:
Test-Command '1' && Test-Command '2'
funciona igual que
Test-Command '1'; if ($?) { Test-Command '2' }
y
Test-Command '1' || Test-Command '2'
funciona igual que
Test-Command '1'; if (-not $?) { Test-Command '2' }
Asignación desde cadenas de canalización
La asignación de una variable de una cadena de canalización toma la concatenación de todas las canalizaciones de la cadena:
$result = Write-Output '1' && Write-Output '2'
$result
1
2
Si se produce un error de terminación de script durante la asignación desde una cadena de canalización, la asignación no se realiza correctamente:
try
{
$result = Write-Output 'Value' && $(throw 'Bad')
}
catch
{
# Do nothing, just squash the error
}
"Result: $result"
Result:
Sintaxis y precedencia del operador
A diferencia de otros operadores, &&
y ||
operan en canalizaciones, en lugar de en expresiones como +
o -and
, por ejemplo.
&&
y ||
tienen una prioridad menor que la canalización (|
) o el redireccionamiento (>
), pero una prioridad más alta que los operadores de trabajo (), la asignación (&
=
) o punto y coma (;
). Esto significa que las canalizaciones dentro de una cadena de canalización se pueden redirigir individualmente y que todas las cadenas de canalización se pueden en segundo plano, asignarlas a variables o separarlas como instrucciones .
Para usar la sintaxis de prioridad inferior dentro de una cadena de canalización, considere el uso de paréntesis (...)
. De forma similar, para insertar una instrucción dentro de una cadena de canalización, se puede usar una subexpresión $(...)
. Esto puede ser útil para combinar comandos nativos con flujo de control:
foreach ($file in 'file1','file2','file3')
{
# When find succeeds, the loop breaks
find $file && Write-Output "Found $file" && $(break)
}
find: file1: No such file or directory
file2
Found file2
A partir de PowerShell 7, se ha cambiado el comportamiento de estas sintaxis para que $?
se establezca según lo previsto cuando un comando se realiza correctamente o produce un error entre paréntesis o una subexpresión.
Al igual que la mayoría de los demás operadores de PowerShell, &&
y ||
también son asociativos a la izquierda, lo que significa que se agrupan desde la izquierda. Por ejemplo:
Get-ChildItem -Path ./file.txt ||
Write-Error "file.txt doesn't exist" &&
Get-Content -Raw ./file.txt
se agrupará como:
(Get-ChildItem -Path ./file.txt || Write-Error "file.txt doesn't exist") &&
Get-Content -Raw ./file.txt
que es equivalente a:
Get-ChildItem -Path ./file.txt
if (-not $?) { Write-Error "file.txt does not exist" }
if ($?) { Get-Content -Raw ./file.txt }
Interacción de errores
Los operadores de cadena de canalización no absorben errores. Cuando una instrucción de una cadena de canalización produce un error de terminación de script, la cadena de canalización finaliza.
Por ejemplo:
$(throw 'Bad') || Write-Output '2'
Exception: Bad
Incluso cuando se detecta el error, la cadena de canalización sigue finalizando:
try
{
$(throw 'Bad') || Write-Output '2'
}
catch
{
Write-Output "Caught: $_"
}
Write-Output 'Done'
Caught: Bad
Done
Si un error no finaliza o solo finaliza una canalización, la cadena de canalización continúa, respetando el valor de $?
:
function Test-NonTerminatingError
{
[CmdletBinding()]
param()
$exception = [System.Exception]::new('BAD')
$errorId = 'BAD'
$errorCategory = 'NotSpecified'
$errorRecord = [System.Management.Automation.ErrorRecord]::new(
$exception, $errorId, $errorCategory, $null
)
$PSCmdlet.WriteError($errorRecord)
}
Test-NonTerminatingError || Write-Output 'Second'
Test-NonTerminatingError: BAD
Second
Encadenar canalizaciones en lugar de comandos
Los operadores de cadena de canalización, por su nombre, se pueden usar para encadenar canalizaciones, en lugar de simplemente comandos. Esto coincide con el comportamiento de otros shells, pero puede hacer que el éxito sea más difícil de determinar:
function Test-NotTwo
{
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline)]
$Input
)
process
{
if ($Input -ne 2)
{
return $Input
}
$exception = [System.Exception]::new('Input is 2')
$errorId = 'InputTwo'
$errorCategory = 'InvalidData'
$errorRecord = [System.Management.Automation.ErrorRecord]::new(
$exception, $errorId, $errorCategory, $null
)
$PSCmdlet.WriteError($errorRecord)
}
}
1,2,3 | Test-NotTwo && Write-Output 'All done!'
1
Test-NotTwo : Input is 2
3
Tenga en cuenta que no se ejecuta, ya Test-NotTwo
que Write-Output 'All done!'
se considera que se ha producido un error después de generar el error de no terminación.
Consulte también
Comentarios
https://aka.ms/ContentUserFeedback.
Próximamente: A lo largo de 2024 iremos eliminando gradualmente GitHub Issues como mecanismo de comentarios sobre el contenido y lo sustituiremos por un nuevo sistema de comentarios. Para más información, vea:Enviar y ver comentarios de