about_Pipeline_Chain_Operators
Krótki opis
Opisuje łączenie potoków z operatorami &&
i ||
w programie PowerShell.
Długi opis
Począwszy od programu PowerShell 7, program PowerShell implementuje &&
operatory i ||
w celu warunkowego tworzenia łańcuchów potoków. Te operatory są znane w programie PowerShell jako operatory łańcucha potoków i są podobne do list AND-OR w powłokach POSIX, takich jak bash, zsh i sh, a także symbole przetwarzania warunkowego w powłoce poleceń systemu Windows (cmd.exe).
Operator &&
wykonuje potok po prawej stronie, jeśli potok po lewej stronie zakończył się pomyślnie. Z drugiej strony operator wykonuje potok po prawej stronie, ||
jeśli potok po lewej stronie zakończył się niepowodzeniem.
Te operatory używają $?
zmiennych i $LASTEXITCODE
, aby określić, czy potok zakończył się niepowodzeniem. Dzięki temu można używać ich z natywnymi poleceniami, a nie tylko z poleceniami cmdlet lub funkcjami. Na przykład:
# 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
Przykłady
Dwa pomyślne polecenia
Write-Output 'First' && Write-Output 'Second'
First
Second
Pierwsze polecenie kończy się niepowodzeniem, co powoduje, że drugie nie jest wykonywane
Write-Error 'Bad' && Write-Output 'Second'
Write-Error: Bad
Pierwsze polecenie powiedzie się, więc drugie polecenie nie jest wykonywane
Write-Output 'First' || Write-Output 'Second'
First
Pierwsze polecenie kończy się niepowodzeniem, więc drugie polecenie jest wykonywane
Write-Error 'Bad' || Write-Output 'Second'
Write-Error: Bad
Second
Powodzenie potoku jest definiowane przez wartość zmiennej $?
, którą program PowerShell automatycznie ustawia po wykonaniu potoku na podstawie stanu jego wykonania.
Oznacza to, że operatorzy łańcucha potoków mają następującą równoważność:
Test-Command '1' && Test-Command '2'
działa tak samo jak
Test-Command '1'; if ($?) { Test-Command '2' }
oraz
Test-Command '1' || Test-Command '2'
działa tak samo jak
Test-Command '1'; if (-not $?) { Test-Command '2' }
Przypisywanie z łańcuchów potoków
Przypisanie zmiennej z łańcucha potoków obejmuje łączenie wszystkich potoków w łańcuchu:
$result = Write-Output '1' && Write-Output '2'
$result
1
2
Jeśli podczas przypisywania z łańcucha potoków wystąpi błąd zakończenia skryptu, przypisanie nie powiedzie się:
try
{
$result = Write-Output 'Value' && $(throw 'Bad')
}
catch
{
# Do nothing, just squash the error
}
"Result: $result"
Result:
Składnia i pierwszeństwo operatora
W przeciwieństwie do innych operatorów &&
i ||
działają na potokach, a nie na wyrażeniach, takich jak +
lub -and
, na przykład.
&&
i ||
mają niższy priorytet niż potok (|
) lub przekierowanie (>
), ale wyższy priorytet niż operatory zadań (), przypisanie (&
=
) lub średniki (;
). Oznacza to, że potoki w łańcuchu potoków mogą być przekierowywane indywidualnie, a całe łańcuchy potoków mogą być w tle, przypisane do zmiennych lub oddzielone jako instrukcje.
Aby użyć składni niższego pierwszeństwa w łańcuchu potoków, rozważ użycie nawiasów (...)
. Podobnie, aby osadzić instrukcję w łańcuchu potoków, można użyć podexpressionu $(...)
. Może to być przydatne w przypadku łączenia natywnych poleceń z przepływem sterowania:
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
Od programu PowerShell 7 zachowanie tych składni zostało zmienione tak, $?
aby było ustawione zgodnie z oczekiwaniami, gdy polecenie zakończy się powodzeniem lub niepowodzeniem w nawiasach lub podrażeniu.
Podobnie jak większość innych operatorów w programie PowerShell, &&
a ||
także są skojarzone z lewej strony, co oznacza, że grupują z lewej strony. Na przykład:
Get-ChildItem -Path ./file.txt ||
Write-Error "file.txt doesn't exist" &&
Get-Content -Raw ./file.txt
grupuje jako:
(Get-ChildItem -Path ./file.txt || Write-Error "file.txt doesn't exist") &&
Get-Content -Raw ./file.txt
jest odpowiednikiem:
Get-ChildItem -Path ./file.txt
if (-not $?) { Write-Error "file.txt does not exist" }
if ($?) { Get-Content -Raw ./file.txt }
Interakcja z błędami
Operatory łańcucha potoków nie pochłaniają błędów. Gdy instrukcja w łańcuchu potoków zgłasza błąd zakończenia skryptu, łańcuch potoków zostanie zakończony.
Na przykład:
$(throw 'Bad') || Write-Output '2'
Exception: Bad
Nawet w przypadku przechwyconego błędu łańcuch potoków jest nadal przerywany:
try
{
$(throw 'Bad') || Write-Output '2'
}
catch
{
Write-Output "Caught: $_"
}
Write-Output 'Done'
Caught: Bad
Done
Jeśli błąd nie kończy się lub kończy tylko potok, łańcuch potoku będzie nadal przestrzegać wartości $?
:
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
Łączenie potoków zamiast poleceń
Operatory łańcucha potoków, według ich nazwy, mogą służyć do tworzenia łańcuchów potoków, a nie tylko poleceń. Jest to zgodne z zachowaniem innych powłok, ale może utrudnić określenie:
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
Należy pamiętać, że Write-Output 'All done!'
nie jest wykonywane, ponieważ Test-NotTwo
jest uważana za niepowodzenie po wygenerowaniu błędu niezwiązanego z kończeniem.
Zobacz też
Opinia
https://aka.ms/ContentUserFeedback.
Dostępne już wkrótce: W 2024 r. będziemy stopniowo wycofywać zgłoszenia z serwisu GitHub jako mechanizm przesyłania opinii na temat zawartości i zastępować go nowym systemem opinii. Aby uzyskać więcej informacji, sprawdź:Prześlij i wyświetl opinię dla