Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Kort beskrivning
Beskriver länkningspipelines med operatorerna && och || i PowerShell.
Lång beskrivning
Från och med PowerShell 7 implementerar PowerShell operatorerna && och || för att villkorligt länka pipelines. Dessa operatorer kallas i PowerShell för pipelinekedjeoperatoreroch liknar AND-OR listor i POSIX-gränssnitt som bash, zsh och sh samt villkorsstyrda bearbetningssymboler i Windows Command Shell (cmd.exe).
Operatorn && kör den högra pipelinen om den vänstra pipelinen lyckades. Omvänt kör ||-operatorn den högra pipelinen om den vänstra pipelinen misslyckades.
Dessa operatorer använder variablerna $? och $LASTEXITCODE för att avgöra om en pipeline misslyckades. På så sätt kan du använda dem med inbyggda kommandon och inte bara med cmdletar eller funktioner. Till exempel:
# 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
Exempel
Två lyckade kommandon
Write-Output 'First' && Write-Output 'Second'
First
Second
Det första kommandot misslyckas, vilket gör att andra inte körs
Write-Error 'Bad' && Write-Output 'Second'
Write-Error: Bad
Det första kommandot lyckas, så det andra kommandot körs inte
Write-Output 'First' || Write-Output 'Second'
First
Det första kommandot misslyckas, så det andra kommandot körs
Write-Error 'Bad' || Write-Output 'Second'
Write-Error: Bad
Second
Pipelineframgång definieras av värdet för variabeln $?, som PowerShell automatiskt anger efter att ha kört en pipeline baserat på dess körningsstatus.
Det innebär att pipelinekedjeoperatorer har följande likvärdighet:
Test-Command '1' && Test-Command '2'
fungerar på samma sätt som
Test-Command '1'; if ($?) { Test-Command '2' }
och
Test-Command '1' || Test-Command '2'
fungerar på samma sätt som
Test-Command '1'; if (-not $?) { Test-Command '2' }
Tilldelning från pipelinekedjor
När du tilldelar en variabel från en pipelinekedja sammanfogas alla pipelines i kedjan:
$result = Write-Output '1' && Write-Output '2'
$result
1
2
Om ett skriptslutfel inträffar under tilldelningen från en pipelinekedja lyckas inte tilldelningen:
try
{
$result = Write-Output 'Value' && $(throw 'Bad')
}
catch
{
# Do nothing, just squash the error
}
"Result: $result"
Result:
Operatorsyntax och prioritet
Till skillnad från andra operatorer fungerar && och || på pipelines, i stället för på uttryck som + eller -and, till exempel.
&& och || har lägre prioritet än rörledningar (|) eller omdirigering (>), men högre prioritet än jobboperatorer (&), tilldelning (=) eller semikolon (;). Det innebär att pipelines i en pipelinekedja kan omdirigeras individuellt och att hela pipelinekedjor kan vara bakgrundskopplade, tilldelade till variabler eller avgränsade som instruktioner.
Om du vill använda lägre prioritetssyntax i en pipelinekedja bör du överväga att använda parenteser (...). Om du vill bädda in en -instruktion i en pipelinekedja kan ett underuttryck $(...) användas. Detta kan vara användbart för att kombinera interna kommandon med kontrollflöde:
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
Från och med PowerShell 7 har beteendet för dessa syntaxer ändrats så att $? anges som förväntat när ett kommando lyckas eller misslyckas inom parenteser eller en underuttryck.
Precis som de flesta andra operatorer i PowerShell är && och || också vänstersociativa, vilket innebär att de grupperas från vänster. Till exempel:
Get-ChildItem -Path ./file.txt ||
Write-Error "file.txt doesn't exist" &&
Get-Content -Raw ./file.txt
grupperas som:
(Get-ChildItem -Path ./file.txt || Write-Error "file.txt doesn't exist") &&
Get-Content -Raw ./file.txt
motsvarar:
Get-ChildItem -Path ./file.txt
if (-not $?) { Write-Error "file.txt does not exist" }
if ($?) { Get-Content -Raw ./file.txt }
Felinteraktion
Pipelinekedjeoperatorer absorberar inte fel. När en instruktion i en pipelinekedja utlöser ett skriptslutfel avslutas pipelinekedjan.
Till exempel:
$(throw 'Bad') || Write-Output '2'
Exception: Bad
Även när felet fångas avslutas pipelinekedjan fortfarande:
try
{
$(throw 'Bad') || Write-Output '2'
}
catch
{
Write-Output "Caught: $_"
}
Write-Output 'Done'
Caught: Bad
Done
Om ett fel inte avslutas eller bara avslutar en pipeline fortsätter pipelinekedjan och respekterar värdet för $?:
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
Länka pipelines i stället för kommandon
Pipelinekedjeoperatorer kan med sitt namn användas för att länka pipelines i stället för bara kommandon. Detta matchar beteendet för andra gränssnitt, men kan göra det svårare att avgöra om det går att lyckas:
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
Observera att Write-Output 'All done!' inte körs eftersom Test-NotTwo anses ha misslyckats efter att det icke-avslutande felet har genererats.