about_Pipeline_Chain_Operators
Krátký popis
Popisuje řetězení kanálů s &&
operátory a ||
operátory v PowerShellu.
Dlouhý popis
Počínaje PowerShellem 7 powershell implementuje operátory &&
a ||
operátory do podmíněně zřetězených kanálů. Tyto operátory jsou známé v PowerShellu jako operátory řetězu kanálů a jsou podobné seznamům AND-OR v prostředích POSIX, jako je bash, zsh a sh, a také symboly podmíněného zpracování v prostředí Windows Command Shell (cmd.exe).
Operátor &&
spustí kanál zprava, pokud byl kanál vlevo úspěšný. Naopak operátor spustí kanál vpravo, ||
pokud kanál vlevo selhal.
Tyto operátory používají $?
proměnné k $LASTEXITCODE
určení, jestli kanál selhal. To vám umožní používat je s nativními příkazy, nejen s rutinami nebo funkcemi. Příklad:
# 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
Příklady
Dva úspěšné příkazy
Write-Output 'First' && Write-Output 'Second'
First
Second
První příkaz selže, což způsobí, že se druhý příkaz nespustí.
Write-Error 'Bad' && Write-Output 'Second'
Write-Error: Bad
První příkaz je úspěšný, takže druhý příkaz se nespustí.
Write-Output 'First' || Write-Output 'Second'
First
První příkaz selže, takže se spustí druhý příkaz.
Write-Error 'Bad' || Write-Output 'Second'
Write-Error: Bad
Second
Úspěch kanálu je definován hodnotou $?
proměnné, kterou PowerShell automaticky nastaví po spuštění kanálu na základě jeho stavu spuštění.
To znamená, že operátory řetězu kanálů mají následující ekvivalenci:
Test-Command '1' && Test-Command '2'
funguje stejně jako
Test-Command '1'; if ($?) { Test-Command '2' }
a
Test-Command '1' || Test-Command '2'
funguje stejně jako
Test-Command '1'; if (-not $?) { Test-Command '2' }
Přiřazení z řetězů kanálů
Přiřazení proměnné z řetězu kanálů přebírá zřetězení všech kanálů v řetězci:
$result = Write-Output '1' && Write-Output '2'
$result
1
2
Pokud během přiřazování z řetězu kanálů dojde k chybě ukončující skript, přiřazení nebude úspěšné:
try
{
$result = Write-Output 'Value' && $(throw 'Bad')
}
catch
{
# Do nothing, just squash the error
}
"Result: $result"
Result:
Syntaxe a priorita operátoru
Na rozdíl od jiných operátorů &&
a ||
pracují s kanály, nikoli s výrazy jako +
nebo -and
, například.
&&
a ||
mají nižší prioritu než potrubí (|
) nebo přesměrování (>
), ale vyšší prioritu než operátory úloh (&
), přiřazení (=
) nebo středníky (;
). To znamená, že kanály v rámci řetězu kanálů je možné jednotlivě přesměrovat a že celé řetězy kanálů můžou být na pozadí, přiřazené proměnným nebo oddělené jako příkazy.
Pokud chcete v řetězu kanálů použít syntaxi s nižší prioritou, zvažte použití závorek (...)
. Podobně lze k vložení příkazu do řetězu kanálů použít dílčí výraz $(...)
. To může být užitečné pro kombinování nativních příkazů s tokem řízení:
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 PowerShellu 7 se chování těchto syntaxí změnilo tak, aby $?
se nastavovalo podle očekávání, když se příkaz úspěšně nebo selže v závorkách nebo podvýrazu.
Stejně jako většina ostatních operátorů v PowerShellu &&
a ||
jsou také asociativní zleva, což znamená, že seskupují zleva. Příklad:
Get-ChildItem -Path ./file.txt ||
Write-Error "file.txt doesn't exist" &&
Get-Content -Raw ./file.txt
seskupí jako:
(Get-ChildItem -Path ./file.txt || Write-Error "file.txt doesn't exist") &&
Get-Content -Raw ./file.txt
odpovídá:
Get-ChildItem -Path ./file.txt
if (-not $?) { Write-Error "file.txt does not exist" }
if ($?) { Get-Content -Raw ./file.txt }
Interakce s chybami
Operátory řetězu kanálů nepohlcují chyby. Když příkaz v řetězu kanálu vyvolá chybu ukončující skript, řetězec kanálu se ukončí.
Příklad:
$(throw 'Bad') || Write-Output '2'
Exception: Bad
I když dojde k zachycení chyby, řetězec kanálu se stále ukončí:
try
{
$(throw 'Bad') || Write-Output '2'
}
catch
{
Write-Output "Caught: $_"
}
Write-Output 'Done'
Caught: Bad
Done
Pokud je chyba neukončující nebo ukončí kanál, řetězec kanálu pokračuje a respektuje hodnotu $?
:
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
Řetězení kanálů místo příkazů
Operátory řetězu kanálů se podle jejich názvu dají použít ke zřetězování kanálů, nikoli jenom příkazů. To odpovídá chování jiných prostředí, ale může ztížit určení úspěchu:
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
Všimněte si, že Write-Output 'All done!'
se nespustí, protože Test-NotTwo
se považuje za neúspěšné po vygenerování neukončující chyby.
Viz také
Váš názor
https://aka.ms/ContentUserFeedback.
Připravujeme: V průběhu roku 2024 budeme postupně vyřazovat problémy z GitHub coby mechanismus zpětné vazby pro obsah a nahrazovat ho novým systémem zpětné vazby. Další informace naleznete v tématu:Odeslat a zobrazit názory pro