about_Pipeline_Chain_Operators
Kurze Beschreibung
Beschreibt die Verkettung von Pipelines mit den &&
Operatoren ||
in PowerShell.
Lange Beschreibung
Ab PowerShell 7 implementiert PowerShell die und ||
die &&
Operatoren in bedingten Verketten von Pipelines. Diese Operatoren sind in PowerShell als Pipelinekettenoperatoren bekannt und ähneln AND-OR-Listen in POSIX-Shells wie Bash, zsh und sh sowie bedingte Verarbeitungssymbole in der Windows-Befehlsshell (cmd.exe).
Der Operator &&
führt die rechte Pipeline aus, wenn die linke Pipeline erfolgreich war. Dagegen führt der Operator ||
die rechte Pipeline aus, wenn die linke Pipeline fehlgeschlagen ist.
Diese Operatoren verwenden die Variablen $?
und $LASTEXITCODE
, um zu bestimmen, ob eine Pipeline fehlgeschlagen ist. Dadurch können Sie sie mit nativen Befehlen und nicht bloß mit Cmdlets oder Funktionen verwenden. Zum Beispiel:
# 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
Beispiele
Zwei erfolgreiche Befehle
Write-Output 'First' && Write-Output 'Second'
First
Second
Der erste Befehl schlägt fehl, was zur Folge hat, dass der zweite Befehl nicht ausgeführt wird.
Write-Error 'Bad' && Write-Output 'Second'
Write-Error: Bad
Der erste Befehl ist erfolgreich, sodass der zweite Befehl nicht ausgeführt wird.
Write-Output 'First' || Write-Output 'Second'
First
Der erste Befehl schlägt fehl, sodass der zweite Befehl ausgeführt wird.
Write-Error 'Bad' || Write-Output 'Second'
Write-Error: Bad
Second
Der Pipelineerfolg wird durch den Wert der $?
Variablen definiert, den PowerShell automatisch nach dem Ausführen einer Pipeline basierend auf dem Ausführungsstatus festlegt.
Dies bedeutet, dass Pipelinekettenbetreiber die folgende Äquivalenz haben:
Test-Command '1' && Test-Command '2'
funktioniert genauso wie
Test-Command '1'; if ($?) { Test-Command '2' }
and
Test-Command '1' || Test-Command '2'
funktioniert genauso wie
Test-Command '1'; if (-not $?) { Test-Command '2' }
Zuordnung aus Pipelineketten
Durch das Zuweisen einer Variablen aus einer Pipelinekette wird die Verkettung aller Pipelines in der Kette verwendet:
$result = Write-Output '1' && Write-Output '2'
$result
1
2
Wenn während der Zuweisung aus einer Pipelinekette ein Skriptendefehler auftritt, ist die Zuordnung nicht erfolgreich:
try
{
$result = Write-Output 'Value' && $(throw 'Bad')
}
catch
{
# Do nothing, just squash the error
}
"Result: $result"
Result:
Operatorsyntax und Rangfolge
Im Gegensatz zu anderen Operatoren &&
und ||
arbeiten Sie nicht auf Ausdrücken wie oder , sondern auf Pipelines wie +
oder -and
beispielsweise.
&&
und ||
haben eine niedrigere Rangfolge als Piping (|
) oder Umleitung (>
), aber eine höhere Rangfolge als Auftragsoperatoren (&
), Zuordnung () oder Semikolons (=
;
). Dies bedeutet, dass Pipelines innerhalb einer Pipelinekette einzeln umgeleitet werden können und dass ganze Pipelineketten hintergrundgebunden, Variablen zugewiesen oder als Anweisungen getrennt werden können.
Wenn Sie eine niedrigere Rangfolgensyntax in einer Pipelinekette verwenden möchten, sollten Sie die Verwendung von Klammern (...)
in Betracht ziehen. Ebenso kann ein Unterausdruck $(...)
verwendet werden, um eine Anweisung in eine Pipelinekette einzubetten. Dies kann nützlich sein, um systemeigene Befehle mit Steuerungsfluss zu kombinieren:
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
Ab PowerShell 7 wurde das Verhalten dieser Syntaxen so geändert, dass sie $?
wie erwartet festgelegt wird, wenn ein Befehl erfolgreich ist oder innerhalb von Klammern oder unter einem Unterausdruck fehlschlägt.
Wie die meisten anderen Operatoren in PowerShell &&
sind sie ||
auch linksassoziativ, d. h. sie gruppieren von links. Zum Beispiel:
Get-ChildItem -Path ./file.txt ||
Write-Error "file.txt doesn't exist" &&
Get-Content -Raw ./file.txt
gruppieren als:
(Get-ChildItem -Path ./file.txt || Write-Error "file.txt doesn't exist") &&
Get-Content -Raw ./file.txt
entspricht:
Get-ChildItem -Path ./file.txt
if (-not $?) { Write-Error "file.txt does not exist" }
if ($?) { Get-Content -Raw ./file.txt }
Fehlerinteraktion
Pipelinekettenoperatoren absorbieren keine Fehler. Wenn eine Anweisung in einer Pipelinekette einen Skriptbeendfehler auslöst, wird die Pipelinekette beendet.
Zum Beispiel:
$(throw 'Bad') || Write-Output '2'
Exception: Bad
Auch wenn der Fehler abgefangen wird, wird die Pipelinekette noch beendet:
try
{
$(throw 'Bad') || Write-Output '2'
}
catch
{
Write-Output "Caught: $_"
}
Write-Output 'Done'
Caught: Bad
Done
Wenn ein Fehler nicht beendet wird oder nur eine Pipeline beendet wird, wird die Pipelinekette fortgesetzt, wobei der Wert von $?
:
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
Verketten von Pipelines anstelle von Befehlen
Pipelinekettenoperatoren können anhand ihres Namens anstelle von Befehlen verkettet werden. Dies entspricht dem Verhalten anderer Shells, kann jedoch die Ermittlung von Erfolg erschweren:This matches the behavior of other shells, but can make success harder to determine:
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
Beachten Sie, dass Write-Output 'All done!'
sie nicht ausgeführt wird, da Test-NotTwo
nach dem Generieren des nicht beendeten Fehlers als fehlgeschlagen gilt.
Weitere Informationen
Feedback
https://aka.ms/ContentUserFeedback.
Bald verfügbar: Im Laufe des Jahres 2024 werden wir GitHub-Issues stufenweise als Feedbackmechanismus für Inhalte abbauen und durch ein neues Feedbacksystem ersetzen. Weitere Informationen finden Sie unterFeedback senden und anzeigen für