about_Pipeline_Chain_Operators

Rövid leírás

A folyamatok a PowerShellben lévő és || operátorokkal && való láncolását ismerteti.

Hosszú leírás

A PowerShell 7-től kezdődően a PowerShell implementálja a folyamatokat és || az && operátorokat a folyamatok feltételes láncba kapcsolásához. Ezek az operátorok a PowerShellben folyamatlánc-operátorokként ismertek, és hasonlóak a POSIX-rendszerhéjak AND-OR listáihoz, például a bashhez, a zsh-hez és az sh-hez, valamint a Windows command Shell feltételes feldolgozási szimbólumaihoz (cmd.exe).

Az && operátor végrehajtja a jobb oldali folyamatot, ha a bal oldali folyamat sikeres volt. Ezzel szemben az || operátor végrehajtja a jobb oldali folyamatot, ha a bal oldali folyamat meghiúsult.

Ezek az operátorok a $?$LASTEXITCODE változókkal határozzák meg, hogy egy folyamat nem sikerült-e. Ez lehetővé teszi, hogy natív parancsokkal és nem csak parancsmagokkal vagy függvényekkel használja őket. Példa:

# 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éldák

Két sikeres parancs

Write-Output 'First' && Write-Output 'Second'
First
Second

Az első parancs meghiúsul, ezért a második nem lesz végrehajtva

Write-Error 'Bad' && Write-Output 'Second'
Write-Error: Bad

Az első parancs sikeres, így a második parancs nem lesz végrehajtva

Write-Output 'First' || Write-Output 'Second'
First

Az első parancs meghiúsul, ezért a második parancs végrehajtása

Write-Error 'Bad' || Write-Output 'Second'
Write-Error: Bad
Second

A folyamat sikerességét a változó értéke határozza meg, amelyet a $? PowerShell automatikusan beállít egy folyamat végrehajtása után a végrehajtási állapot alapján. Ez azt jelenti, hogy a folyamatlánc-operátorok a következő egyenértékűséggel rendelkeznek:

Test-Command '1' && Test-Command '2'

ugyanúgy működik, mint a

Test-Command '1'; if ($?) { Test-Command '2' }

és

Test-Command '1' || Test-Command '2'

ugyanúgy működik, mint a

Test-Command '1'; if (-not $?) { Test-Command '2' }

Hozzárendelés folyamatláncokból

Egy változó folyamatláncból való hozzárendelése a lánc összes folyamatának összefűzésével történik:

$result = Write-Output '1' && Write-Output '2'
$result
1
2

Ha egy folyamatláncból való hozzárendelés során szkript-megszakítási hiba történik, a hozzárendelés nem sikerül:

try
{
    $result = Write-Output 'Value' && $(throw 'Bad')
}
catch
{
    # Do nothing, just squash the error
}

"Result: $result"
Result:

Operátor szintaxisa és elsőbbsége

A többi operátortól && eltérően, és || a folyamatokon, nem pedig például a hasonló vagy -andhasonló + kifejezéseken kell dolgoznia.

&& és || alacsonyabb elsőbbséget élveznek, mint a piping (|) vagy az átirányítás (>), de magasabb elsőbbséget élveznek, mint a feladatoperátorok (&), a hozzárendelés (=) vagy a pontosvesszők (;). Ez azt jelenti, hogy a folyamatláncon belüli folyamatok külön-külön irányíthatók át, és a teljes folyamatláncok háttérbe állíthatók, változókhoz rendelhetők, vagy utasításokként elválaszthatók.

Ha a folyamatláncon belül alacsonyabb precedensszintaxist szeretne használni, vegye figyelembe a zárójelek (...)használatát. Hasonlóképpen, egy utasítás folyamatláncba való beágyazásához alexpresszió $(...) is használható. Ez hasznos lehet a natív parancsok és a vezérlési folyamat kombinálásához:

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

A PowerShell 7-hez hasonlóan ezen szintaxisok viselkedése módosult, így $? a rendszer a vártnak megfelelően állítja be, ha egy parancs sikeres vagy meghiúsul zárójelben vagy alkifejezésben.

A PowerShell többi operátorához hasonlóan bal &&|| asszociatívak is, ami azt jelenti, hogy balról csoportosítanak. Példa:

Get-ChildItem -Path ./file.txt ||
    Write-Error "file.txt doesn't exist" &&
    Get-Content -Raw ./file.txt

csoportosítása a következő lesz:

(Get-ChildItem -Path ./file.txt || Write-Error "file.txt doesn't exist") &&
    Get-Content -Raw ./file.txt

egyenértékű a következő értékeket:

Get-ChildItem -Path ./file.txt

if (-not $?) { Write-Error "file.txt does not exist" }

if ($?) { Get-Content -Raw ./file.txt }

Hiba interakciója

A folyamatlánc-operátorok nem veszik fel a hibákat. Amikor egy folyamatlánc egy utasítása parancsfájl-megszakítási hibát jelez, a folyamatlánc leáll.

Példa:

$(throw 'Bad') || Write-Output '2'
Exception: Bad

A folyamatlánc még a hiba észlelésekor is leáll:

try
{
    $(throw 'Bad') || Write-Output '2'
}
catch
{
    Write-Output "Caught: $_"
}
Write-Output 'Done'
Caught: Bad
Done

Ha egy hiba nem szűnik meg, vagy csak egy folyamatot zár le, a folyamatlánc folytatódik, a következő érték figyelembevételével $?:

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

Folyamatok láncolása parancsok helyett

A folyamatlánc-operátorok nevük szerint a parancsok helyett a folyamatok láncolataként is használhatók. Ez megegyezik a többi rendszerhéj viselkedésével, de megnehezítheti a sikeresség megállapítását:

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

Vegye figyelembe, hogy Write-Output 'All done!' a művelet nem lett végrehajtva, mivel Test-NotTwo a nem végződő hiba generálása után meghiúsultnak minősül.

Lásd még