tentang_Operator_Rantai_Pipeline

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. Misalnya:

# 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 perintah kedua 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 ditetapkan PowerShell secara otomatis setelah menjalankan alur berdasarkan status eksekusinya. Ini berarti bahwa operator rantai alur memiliki kesetaraan berikut:

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

berfungsi sama seperti

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

dan

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

berfungsi sama seperti

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

Penugasan dari rantai alur

Menetapkan variabel dari rangkaian pipeline melibatkan penggabungan semua pipeline dalam rantai tersebut.

$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 pipeline, bukan pada ekspresi seperti + atau -and, misalnya.

&& dan || memiliki prioritas yang lebih rendah daripada pengaluran (|) atau pengalihan (>), tetapi prioritas yang lebih tinggi daripada operator tugas (&), 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. Misalnya:

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 menghasilkan kesalahan yang menghentikan skrip, rantai alur tersebut akan dihentikan.

Misalnya:

$(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 bagian dari alur, rangkaian alur berlanjut, sesuai dengan 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 hasil yang berhasil lebih sulit ditentukan.

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 dieksekusi, karena Test-NotTwo dianggap gagal setelah menghasilkan kesalahan yang tidak menghentikan proses.

Lihat juga