Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Kurzbeschreibung
Beschreibt die Verkettung von Pipelines mit dem && und || Operatoren in PowerShell.
Lange Beschreibung
Ab PowerShell 7 implementiert PowerShell das && und || Operatoren zur bedingten Verkettung von Pipelines. Diese Operatoren sind in PowerShell bekannt als Pipeline-Kettenbetreiber, und sind vergleichbar mit AND-OR-Listen in POSIX-Shells wie bash, zsh und sh, sowie in Symbole für die bedingte Verarbeitung in der Windows Command Shell (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 ermitteln, ob eine Pipeline fehlgeschlagen ist. Auf diese Weise können Sie sie mit nativen Befehlen und nicht nur 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, die PowerShell nach der Ausführung einer Pipeline basierend auf ihrem Ausführungsstatus automatisch 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' }
und
Test-Command '1' || Test-Command '2'
funktioniert genauso wie
Test-Command '1'; if (-not $?) { Test-Command '2' }
Zuordnung von Pipeline-Ketten
Für die Zuweisung einer Variablen aus einer Pipeline-Kette ist die Verkettung aller Pipelines in der Kette erforderlich:
$result = Write-Output '1' && Write-Output '2'
$result
1
2
Wenn während der Zuweisung aus einer Pipeline-Kette ein Skript-Beendigungsfehler auftritt, ist die Zuweisung nicht erfolgreich:
try
{
$result = Write-Output 'Value' && $(throw 'Bad')
}
catch
{
# Do nothing, just squash the error
}
"Result: $result"
Result:
Syntax und Vorrang von Operatoren
Im Gegensatz zu anderen Betreibern, && und || auf Pipelines wirken und nicht auf Ausdrücke wie + oder -and, zum Beispiel.
&& und || haben einen geringeren Vorrang als Rohrleitungen (|) oder Umleitung (>), aber einen höheren Vorrang als Job-Operatoren (&), Auftrag (=) oder Semikolons (;). Das bedeutet, dass Pipelines innerhalb einer Pipeline-Kette einzeln umgeleitet werden können und dass ganze Pipeline-Ketten in den Hintergrund gestellt, Variablen zugewiesen oder als Anweisungen getrennt werden können.
Um eine Syntax mit niedrigerem Vorrang innerhalb einer Pipelinekette zu verwenden, sollten Sie Klammern verwenden (...). Um eine Anweisung in eine Pipeline-Kette einzubetten, muss ein Unterausdruck $(...) verwendet werden können. Dies kann nützlich sein, um native Befehle mit Kontrollfluss 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 dahingehend geändert, dass $? wird wie erwartet gesetzt, wenn ein Befehl innerhalb von Klammern oder einem Unterausdruck erfolgreich ist oder fehlschlägt.
Wie die meisten anderen Operatoren in PowerShell, && und || sind auch links-assoziativ, das heißt, sie gruppieren sich 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
gleichwertig zu sein:
Get-ChildItem -Path ./file.txt
if (-not $?) { Write-Error "file.txt does not exist" }
if ($?) { Get-Content -Raw ./file.txt }
Fehler-Interaktion
Die Betreiber von Pipeline-Ketten absorbieren keine Fehler. Wenn eine Anweisung in einer Pipeline-Kette einen Fehler bei der Beendigung des Skripts auslöst, wird die Pipeline-Kette abgebrochen.
Zum Beispiel:
$(throw 'Bad') || Write-Output '2'
Exception: Bad
Auch wenn der Fehler abgefangen wird, wird die Pipeline-Kette abgebrochen:
try
{
$(throw 'Bad') || Write-Output '2'
}
catch
{
Write-Output "Caught: $_"
}
Write-Output 'Done'
Caught: Bad
Done
Wenn ein Fehler nicht abschließend ist oder nur eine Pipeline abbricht, wird die Pipeline-Kette unter Berücksichtigung des Wertes 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
Verkettung von Pipelines anstelle von Befehlen
Pipeline-Kettenoperatoren können, wie der Name schon sagt, zur Verkettung von Pipelines und nicht nur von Befehlen verwendet werden. Dies entspricht dem Verhalten anderer Muscheln, macht es aber schwieriger, den Erfolg zu bestimmen:
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!' wird nicht ausgeführt, da Test-NotTwo gilt als gescheitert, nachdem der nicht abschließende Fehler erzeugt wurde.