about_Pipeline_Chain_Operators

Kısa açıklama

PowerShell'deki 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 için 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 taraftaki işlem hattı başarılı olursa sağ taraftaki işlem hattını yürütür. Buna karşılık, || sol taraftaki 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. Örnek:

# 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 saniyenin yürütülmemesi

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

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

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şkeninin 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'

aynı şekilde çalışır

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

ve

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

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ştirilmiş işlemini alır:

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

İşlem hattı zincirinden atama sırasında 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, bir işlem hattı zinciri içindeki işlem hatlarının tek tek yeniden yönlendirilebileceği ve işlem hattı zincirlerinin tamamının arka planlı olarak oluşturulabileceği, değişkenlere atanabileceği veya deyimler 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 itibarıyla, 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ırlar. Örnek:

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ı emmez. İşlem hattı zincirindeki bir deyim betik sonlandırıcı bir hata oluşturursa işlem hattı zinciri sonlandırılır.

Örnek:

$(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 olarak kullanmak 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!' hatanın oluşturulmasından sonra başarısız olduğu varsayıldığından yürütülmediğini Test-NotTwo unutmayın.

Ayrıca bkz.