Aracılığıyla paylaş


about_Pipeline_Chain_Operators

Kısa açıklama

PowerShell'de ve || işleçleriyle && zincirleme işlem hatlarını açıklar.

Uzun açıklama

PowerShell 7'de başlayarak PowerShell, işlem hatlarını && koşullu olarak zincirleme amacıyla ve || işleçlerini uygular. Bu işleçler PowerShell'de işlem hattı zinciri işleçleri olarak bilinir ve bash, zsh ve sh gibi POSIX kabuklarındaki AND-OR listelerinin yanı sıra Windows Komut Kabuğu'ndaki (cmd.exe) koşullu işleme simgelerine benzer.

İşleç && , sol işlem hattı başarılı olursa sağ işlem hattını yürütür. Buna karşılık, || sol işlem hattı başarısız olursa işleç sağ işlem hattını yürütür.

Bu işleçler, işlem hattının $? başarısız olup olmadığını belirlemek için ve $LASTEXITCODE değişkenlerini kullanır. Bu, bunları yalnızca cmdlet'ler veya işlevlerle değil yerel komutlarla kullanmanıza olanak tanır. Örneğin:

# 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

Örnekler

İki başarılı komut

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

İlk komut başarısız olur ve ikincinin yürütülememesine neden olur

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

İlk komut başarılı olur, bu nedenle ikinci komut yürütülmez

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

İlk komut başarısız olduğundan ikinci komut yürütülür

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

İşlem hattı başarısı, PowerShell'in $? yürütme durumuna göre bir işlem hattı yürüttükten sonra otomatik olarak ayarladığı değişkenin değeriyle tanımlanır. Bu, işlem hattı zinciri işleçlerinin aşağıdaki eşdeğerliğe sahip olduğu anlamına gelir:

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

ile aynı şekilde çalışır

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

ve

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

ile aynı şekilde çalışır

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

İşlem hattı zincirlerinden atama

bir işlem hattı zincirinden değişken atamak, zincirdeki tüm işlem hatlarının birleştirmesini alır:

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

İşlem hattı zincirinden atama sırasında bir betik sonlandırma hatası oluşursa atama başarılı olmaz:

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

"Result: $result"
Result:

İşleç söz dizimi ve öncelik

Diğer işleçlerden && farklı olarak veya || gibi +-andifadeler yerine işlem hatlarında çalışır.

&&ve || iş işleçlerinden (), atamadan= (|) veya> noktalı virgülden; (&) daha düşük önceliğe sahiptir. Bu, işlem hattı zincirindeki işlem hatlarının tek tek yeniden yönlendirilebileceği ve işlem hattı zincirlerinin tamamının arka planlı olarak, değişkenlere atanabileceği veya deyim olarak ayrılabileceği anlamına gelir.

İşlem hattı zincirinde daha düşük öncelik söz dizimi kullanmak için parantez (...)kullanımını göz önünde bulundurun. Benzer şekilde, bir deyimi bir işlem hattı zincirine eklemek için bir alt ifade $(...) kullanılabilir. Bu, yerel komutları denetim akışıyla birleştirmek için yararlı olabilir:

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

PowerShell 7'de bu söz dizimlerinin davranışı, bir komut parantez veya alt ifade içinde başarılı olduğunda veya başarısız olduğunda beklendiği gibi ayarlı olacak şekilde değiştirilmiştir $? .

PowerShell'deki && diğer işleçlerin çoğu gibi ve || aynı zamanda soldan ilişkilendirilir, yani soldan gruplandırılır. Örneğin:

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

şu şekilde gruplandırılır:

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

şu değere eşdeğerdir:

Get-ChildItem -Path ./file.txt

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

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

Hata etkileşimi

İşlem hattı zinciri işleçleri hataları emmiyor. İşlem hattı zincirindeki bir deyim betik sonlandırıcı bir hata oluşturursa işlem hattı zinciri sonlandırılır.

Örneğin:

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

Hata yakalansa bile işlem hattı zinciri sonlandırılır:

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

Bir hata sonlandırıcı değilse veya yalnızca bir işlem hattını sonlandırırsa, işlem hattı zinciri değerini $?dikkate alan devam eder:

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

Komutlar yerine işlem hatlarını zincirleme

İşlem hattı zinciri işleçleri, yalnızca komutlar yerine işlem hatlarını zincirleme için kullanılabilir. Bu, diğer kabukların davranışıyla eşleşir, ancak başarının belirlenmesini zorlaştırabilir:

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

Sonlandırılmayan Write-Output 'All done!' hata oluştuktan sonra başarısız olduğu varsayıldığından yürütülmediğini Test-NotTwo unutmayın.

Ayrıca bkz.