about_Pipeline_Chain_Operators
Breve descrição
Descreve o encadeamento de pipelines com os &&
operadores e ||
no PowerShell.
Descrição longa
A partir do PowerShell 7, o PowerShell implementa os &&
operadores e ||
para encadear condicionalmente pipelines. Esses operadores são conhecidos no PowerShell como operadores de cadeia de pipeline e são semelhantes às listas AND-OR em shells POSIX como bash, zsh e sh, bem como símbolos de processamento condicional no Shell de Comando do Windows (cmd.exe).
O &&
operador executa o pipeline do lado direito, se o pipeline do lado esquerdo for bem-sucedido. Por outro lado, o ||
operador executa o pipeline do lado direito se o pipeline do lado esquerdo falhar.
Esses operadores usam as $?
variáveis e $LASTEXITCODE
para determinar se um pipeline falhou. Isso permite que você os use com comandos nativos e não apenas com cmdlets ou funções. Por exemplo:
# 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
Exemplos
Dois comandos bem-sucedidos
Write-Output 'First' && Write-Output 'Second'
First
Second
O primeiro comando falha, fazendo com que o segundo não seja executado
Write-Error 'Bad' && Write-Output 'Second'
Write-Error: Bad
O primeiro comando é bem-sucedido, portanto, o segundo comando não é executado
Write-Output 'First' || Write-Output 'Second'
First
O primeiro comando falha, então o segundo comando é executado
Write-Error 'Bad' || Write-Output 'Second'
Write-Error: Bad
Second
O sucesso do pipeline é definido pelo valor da variável, que o $?
PowerShell define automaticamente após a execução de um pipeline com base em seu status de execução.
Isto significa que os operadores da cadeia de oleodutos têm a seguinte equivalência:
Test-Command '1' && Test-Command '2'
funciona da mesma forma que
Test-Command '1'; if ($?) { Test-Command '2' }
e
Test-Command '1' || Test-Command '2'
funciona da mesma forma que
Test-Command '1'; if (-not $?) { Test-Command '2' }
Atribuição a partir de cadeias de oleodutos
A atribuição de uma variável de uma cadeia de pipeline leva a concatenação de todos os pipelines na cadeia:
$result = Write-Output '1' && Write-Output '2'
$result
1
2
Se ocorrer um erro de terminação de script durante a atribuição de uma cadeia de pipeline, a atribuição não terá êxito:
try
{
$result = Write-Output 'Value' && $(throw 'Bad')
}
catch
{
# Do nothing, just squash the error
}
"Result: $result"
Result:
Sintaxe e precedência do operador
Ao contrário de outros operadores, &&
e ||
operam em gasodutos, em vez de em expressões como +
ou -and
, por exemplo.
&&
e ||
têm uma precedência menor do que tubulação (|
) ou redirecionamento (>
), mas uma precedência maior do que operadores de trabalho (&
), atribuição (=
) ou ponto-e-vírgula (;
). Isso significa que os pipelines dentro de uma cadeia de pipeline podem ser redirecionados individualmente e que cadeias de pipeline inteiras podem ser colocadas em segundo plano, atribuídas a variáveis ou separadas como instruções.
Para usar a sintaxe de precedência mais baixa dentro de uma cadeia de pipeline, considere o uso de parênteses (...)
. Da mesma forma, para incorporar uma instrução dentro de uma cadeia de pipeline, uma subexpressão $(...)
pode ser usada. Isso pode ser útil para combinar comandos nativos com fluxo de controle:
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 do PowerShell 7, o comportamento dessas sintaxes foi alterado para que $?
seja definido como esperado quando um comando for bem-sucedido ou falhar entre parênteses ou uma subexpressão.
Como a maioria dos outros operadores no PowerShell, &&
e ||
também são associados à esquerda, o que significa que eles se agrupam a partir da esquerda. Por exemplo:
Get-ChildItem -Path ./file.txt ||
Write-Error "file.txt doesn't exist" &&
Get-Content -Raw ./file.txt
agrupar-se-á como:
(Get-ChildItem -Path ./file.txt || Write-Error "file.txt doesn't exist") &&
Get-Content -Raw ./file.txt
ser equivalente a:
Get-ChildItem -Path ./file.txt
if (-not $?) { Write-Error "file.txt does not exist" }
if ($?) { Get-Content -Raw ./file.txt }
Interação de erro
Os operadores da cadeia de oleodutos não absorvem erros. Quando uma instrução em uma cadeia de pipeline gera um erro de terminação de script, a cadeia de pipeline é encerrada.
Por exemplo:
$(throw 'Bad') || Write-Output '2'
Exception: Bad
Mesmo quando o erro é detetado, a cadeia de oleodutos ainda é encerrada:
try
{
$(throw 'Bad') || Write-Output '2'
}
catch
{
Write-Output "Caught: $_"
}
Write-Output 'Done'
Caught: Bad
Done
Se um erro não terminar ou apenas encerrar um pipeline, a cadeia de pipeline continuará, respeitando o 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
Encadeamento de pipelines em vez de comandos
Os operadores de cadeia de oleodutos, pelo seu nome, podem ser usados para encadear oleodutos, em vez de apenas comandos. Isso corresponde ao comportamento de outros shells, mas pode tornar o sucesso mais 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
Observe que Write-Output 'All done!'
não é executado, pois Test-NotTwo
é considerado como tendo falhado após gerar o erro de não terminação.
Consulte também
Comentários
https://aka.ms/ContentUserFeedback.
Brevemente: Ao longo de 2024, vamos descontinuar progressivamente o GitHub Issues como mecanismo de feedback para conteúdos e substituí-lo por um novo sistema de feedback. Para obter mais informações, veja:Submeter e ver comentários