about_Pipeline_Chain_Operators

Deskripsi singkat

Menjelaskan alur penautan dengan && operator dan || di PowerShell.

Deskripsi panjang

Dimulai di PowerShell 7, PowerShell mengimplementasikan && operator dan || untuk menautkan alur secara kondisional. Operator ini dikenal di PowerShell sebagai operator rantai alur, dan mirip dengan daftar AND-OR dalam shell POSIX seperti bash, zsh dan sh, serta simbol pemrosesan bersyarat di Windows Command Shell (cmd.exe).

Operator && menjalankan alur sebelah kanan, jika alur sebelah kiri berhasil. Sebaliknya, || operator menjalankan alur sebelah kanan jika alur sebelah kiri gagal.

Operator ini menggunakan $? variabel dan $LASTEXITCODE untuk menentukan apakah alur gagal. Ini memungkinkan Anda untuk menggunakannya dengan perintah asli dan tidak hanya dengan cmdlet atau fungsi. Contohnya:

# 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

Contoh

Dua perintah berhasil

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

Perintah pertama gagal, menyebabkan detik tidak dijalankan

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

Perintah pertama berhasil, sehingga perintah kedua tidak dijalankan

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

Perintah pertama gagal, sehingga perintah kedua dijalankan

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

Keberhasilan alur didefinisikan oleh nilai $? variabel, yang secara otomatis ditetapkan PowerShell setelah menjalankan alur berdasarkan status eksekusinya. Ini berarti bahwa operator rantai alur memiliki kesetaraan berikut:

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

bekerja sama seperti

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

dan

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

bekerja sama seperti

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

Penugasan dari rantai alur

Menetapkan variabel dari rantai alur mengambil perangkaian semua alur dalam rantai:

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

Jika kesalahan penghentian skrip terjadi selama penugasan dari rantai alur, penugasan tidak berhasil:

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

"Result: $result"
Result:

Sintaks dan prioritas operator

Tidak seperti operator lain, && dan || beroperasi pada alur, bukan pada ekspresi seperti + atau -and, misalnya.

&& dan || memiliki prioritas yang lebih rendah daripada pipa (|) atau pengalihan (>), tetapi prioritas yang lebih tinggi daripada operator pekerjaan (&), penugasan (=) atau titik koma (;). Ini berarti bahwa alur dalam rantai alur dapat dialihkan secara individual, dan bahwa seluruh rantai alur dapat di latar belakang, ditetapkan ke variabel, atau dipisahkan sebagai pernyataan.

Untuk menggunakan sintaks prioritas yang lebih rendah dalam rantai alur, pertimbangkan penggunaan tanda kurung (...). Demikian pula, untuk menyematkan pernyataan dalam rantai alur, subekspresi $(...) dapat digunakan. Ini dapat berguna untuk menggabungkan perintah asli dengan alur kontrol:

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

Pada PowerShell 7, perilaku sintaksis ini telah diubah sehingga diatur seperti yang $? diharapkan ketika perintah berhasil atau gagal dalam tanda kurung atau subekspresi.

Seperti kebanyakan operator lain di PowerShell, && dan || juga asosiatif kiri, yang berarti mereka mengelompokkan dari kiri. Contohnya:

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

akan mengelompokkan sebagai:

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

setara dengan:

Get-ChildItem -Path ./file.txt

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

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

Interaksi kesalahan

Operator rantai alur tidak menyerap kesalahan. Ketika pernyataan dalam rantai alur melemparkan kesalahan penghentian skrip, rantai alur dihentikan.

Contohnya:

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

Bahkan ketika kesalahan tertangkap, rantai alur masih dihentikan:

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

Jika kesalahan tidak mengakhiri, atau hanya mengakhiri alur, rantai alur berlanjut, menghormati nilai $?:

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

Menautkan alur daripada perintah

Operator rantai alur, berdasarkan namanya, dapat digunakan untuk menautkan alur, bukan hanya perintah. Ini cocok dengan perilaku shell lain, tetapi dapat membuat kesuksesan lebih sulit untuk menentukan:

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

Perhatikan bahwa Write-Output 'All done!' tidak dijalankan, Test-NotTwo karena dianggap gagal setelah menghasilkan kesalahan yang tidak mengakhiri.

Lihat juga