Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Krótki opis
Opisuje łączenie potoków za pomocą operatorów &&
i ||
w programie PowerShell.
Długi opis
Począwszy od programu PowerShell 7, program PowerShell implementuje operatory &&
i ||
do warunkowego łańcucha potoków. Te operatory są znane w programie PowerShell jako operatory łańcucha potoków i są podobne do list AND-OR list 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óra 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' }
i
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ć $(...)
podrażenia. 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, &&
i ||
są również po lewej stronie, co oznacza, że grupują od lewej. 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 potoków będzie kontynuowany, szanując wartość $?
:
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 wykonywana, ponieważ Test-NotTwo
jest uważana za nieudaną po wygenerowaniu błędu bez zakończenia.