about_Pipeline_Chain_Operators
Korte beschrijving
Beschrijft het koppelen van pijplijnen met de && en || operators in PowerShell.
Lange beschrijving
Vanaf PowerShell 7 implementeert PowerShell de && en || operators om pijplijnen voorwaardelijk te koppelen. Deze operators zijn bekend in PowerShell als operatoren voor pijplijnketens en zijn vergelijkbaar met AND-OR-lijsten in POSIX-shells , zoals bash, zsh en sh, evenals symbolen voor voorwaardelijke verwerking in de Windows Command Shell (cmd.exe).
De && operator voert de rechterpijplijn uit als de linkerpijplijn is geslaagd. Omgekeerd voert de || operator de rechterpijplijn uit als de linkerpijplijn is mislukt.
Deze operators gebruiken de $? en $LASTEXITCODE variabelen om te bepalen of een pijplijn is mislukt. Hierdoor kunt u ze gebruiken met systeemeigen opdrachten en niet alleen met cmdlets of functies. Bijvoorbeeld:
# 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
Voorbeelden
Twee geslaagde opdrachten
Write-Output 'First' && Write-Output 'Second'
First
Second
Eerste opdracht mislukt, waardoor de tweede niet wordt uitgevoerd
Write-Error 'Bad' && Write-Output 'Second'
Write-Error: Bad
De eerste opdracht slaagt, dus de tweede opdracht wordt niet uitgevoerd
Write-Output 'First' || Write-Output 'Second'
First
Eerste opdracht mislukt, dus de tweede opdracht wordt uitgevoerd
Write-Error 'Bad' || Write-Output 'Second'
Write-Error: Bad
Second
Het succes van de pijplijn wordt gedefinieerd door de waarde van de $? variabele, die door PowerShell automatisch wordt ingesteld na het uitvoeren van een pijplijn op basis van de uitvoeringsstatus.
Dit betekent dat operators van pijplijnketens de volgende equivalentie hebben:
Test-Command '1' && Test-Command '2'
werkt hetzelfde als
Test-Command '1'; if ($?) { Test-Command '2' }
en
Test-Command '1' || Test-Command '2'
werkt hetzelfde als
Test-Command '1'; if (-not $?) { Test-Command '2' }
Toewijzing van pijplijnketens
Als u een variabele uit een pijplijnketen toewijst, wordt de samenvoeging van alle pijplijnen in de keten gebruikt:
$result = Write-Output '1' && Write-Output '2'
$result
1
2
Als er een scripteindingsfout optreedt tijdens de toewijzing vanuit een pijplijnketen, slaagt de toewijzing niet:
try
{
$result = Write-Output 'Value' && $(throw 'Bad')
}
catch
{
# Do nothing, just squash the error
}
"Result: $result"
Result:
Operatorsyntaxis en prioriteit
In tegenstelling tot andere operators en &&|| werken ze op pijplijnen, in plaats van op expressies zoals + of -andbijvoorbeeld.
&&en || hebben een lagere prioriteit dan piping () of omleiding (|>), maar een hogere prioriteit dan taakoperators (&), toewijzing (=) of puntkomma's (;). Dit betekent dat pijplijnen binnen een pijplijnketen afzonderlijk kunnen worden omgeleid en dat hele pijplijnketens kunnen worden achtergrond, toegewezen aan variabelen of als instructies kunnen worden gescheiden.
Als u een lagere prioriteitsyntaxis binnen een pijplijnketen wilt gebruiken, kunt u het gebruik van haakjes (...)overwegen.
Op dezelfde manier kan een subexpressie $(...) worden gebruikt om een instructie in een pijplijnketen in te sluiten.
Dit kan handig zijn voor het combineren van systeemeigen opdrachten met controlestroom:
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
Vanaf PowerShell 7 is het gedrag van deze syntaxis gewijzigd, zodat deze $? wordt ingesteld zoals verwacht wanneer een opdracht slaagt of mislukt tussen haakjes of een subexpressie.
Net als de meeste andere operators in PowerShell en &&|| zijn ze ook links-associatief, wat betekent dat ze van links groeperen. Bijvoorbeeld:
Get-ChildItem -Path ./file.txt || Write-Error "file.txt does not exist" && Get-Content -Raw ./file.txt
wordt gegroepeerd als:
[Get-ChildItem -Path ./file.txt || Write-Error "file.txt does not exist"] && Get-Content -Raw ./file.txt
gelijkwaardig zijn aan:
Get-ChildItem -Path ./file.txt
if (-not $?) { Write-Error "file.txt does not exist" }
if ($?) { Get-Content -Raw ./file.txt }
Foutinteractie
Operators voor pijplijnketens nemen geen fouten op. Wanneer een instructie in een pijplijnketen een scripteindingsfout genereert, wordt de pijplijnketen beëindigd.
Bijvoorbeeld:
$(throw 'Bad') || Write-Output '2'
Exception: Bad
Zelfs wanneer de fout wordt gepakt, wordt de pijplijnketen nog steeds beëindigd:
try
{
$(throw 'Bad') || Write-Output '2'
}
catch
{
Write-Output "Caught: $_"
}
Write-Output 'Done'
Caught: Bad
Done
Als een fout niet is beëindigd of alleen een pijplijn beëindigt, blijft de pijplijnketen doorgaan, waarbij de waarde van $?:
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
Pijplijnen koppelen in plaats van opdrachten
Pijplijnketenoperators kunnen op hun naam worden gebruikt om pijplijnen te koppelen, in plaats van alleen opdrachten. Dit komt overeen met het gedrag van andere shells, maar kan het succes moeilijker maken om te bepalen:
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
Houd er rekening mee dat Write-Output 'All done!' deze niet wordt uitgevoerd, omdat Test-NotTwo deze wordt geacht te zijn mislukt nadat de niet-afsluitfout is gegenereerd.