Share via


about_Pipeline_Chain_Operators

간단한 설명

PowerShell에서 파이프라인과 || 연산자를 && 연결하는 것에 대해 설명합니다.

자세한 설명

PowerShell 7부터 PowerShell은 파이프라인을 && 조건부로 연결하는 연 || 산자를 구현합니다. 이러한 연산자는 PowerShell에서 파이프라인 체인 연산자로 알려져 있으며 bash, zsh 및 sh와 같은 POSIX 셸의 AND-OR 목록뿐만 아니라 Windows 명령 셸(cmd.exe)의 조건부 처리 기호와 비슷합니다.

&& 왼쪽 파이프라인이 성공한 경우 연산자는 오른쪽 파이프라인을 실행합니다. 반대로, 왼쪽 파이프라인이 || 실패한 경우 연산자는 오른쪽 파이프라인을 실행합니다.

이러한 연산자는 $?$LASTEXITCODE 변수를 사용하여 파이프라인이 실패했는지 확인합니다. 이렇게 하면 cmdlet 또는 함수뿐만 아니라 네이티브 명령과 함께 사용할 수 있습니다. 다음은 그 예입니다.

# 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

두 개의 성공적인 명령

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

첫 번째 명령이 실패하여 두 번째 명령이 실행되지 않음

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

첫 번째 명령이 성공하므로 두 번째 명령이 실행되지 않습니다.

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

첫 번째 명령이 실패하므로 두 번째 명령이 실행됩니다.

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

파이프라인 성공은 실행 상태 따라 파이프라인을 실행한 후 PowerShell이 자동으로 설정하는 변수 값 $? 으로 정의됩니다. 즉, 파이프라인 체인 연산자는 다음과 같은 동등성을 갖습니다.

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

과 동일하게 작동합니다.

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

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

과 동일하게 작동합니다.

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

파이프라인 체인에서 할당

파이프라인 체인에서 변수를 할당하면 체인의 모든 파이프라인이 연결됩니다.

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

파이프라인 체인에서 할당하는 동안 스크립트 종료 오류가 발생하면 할당이 성공하지 못합니다.

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

"Result: $result"
Result:

연산자 구문 및 우선 순위

예를 들어 다른 연산 && 자와 || 달리 식이 +-and아닌 파이프라인에서 작동합니다.

&&|| 파이핑() 또는 리디렉션(|>)보다 우선 순위가 낮지만 작업 연산자(), 할당(&) 또는 세미콜론(=)보다 우선 순위가; 높습니다. 즉, 파이프라인 체인 내의 파이프라인을 개별적으로 리디렉션할 수 있으며 전체 파이프라인 체인을 백그라운드로 지정하거나 변수에 할당하거나 문으로 구분할 수 있습니다.

파이프라인 체인 내에서 우선 순위가 낮은 구문을 사용하려면 괄호를 사용하는 것이 좋습니다 (...). 마찬가지로 파이프라인 체인 내에 문을 포함하기 위해 하위 식 $(...) 이 사용될 수 있습니다. 이는 네이티브 명령을 제어 흐름과 결합하는 데 유용할 수 있습니다.

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부터 명령이 괄호 또는 하위 식 내에서 성공하거나 실패할 때 예상대로 설정되도록 $? 이러한 구문의 동작이 변경되었습니다.

PowerShell && 의 대부분의 다른 연산자와 || 마찬가지로 왼쪽 연결있습니다. 즉, 왼쪽에서 그룹화됩니다. 예시:

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

는 다음으로 그룹화됩니다.

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

은 다음과 같습니다.

Get-ChildItem -Path ./file.txt

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

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

오류 상호 작용

파이프라인 체인 연산자는 오류를 흡수하지 않습니다. 파이프라인 체인의 문이 스크립트 종료 오류를 throw하면 파이프라인 체인이 종료됩니다.

예시:

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

오류가 발견되더라도 파이프라인 체인은 여전히 종료됩니다.

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

오류가 종료되지 않거나 파이프라인만 종료하는 경우 파이프라인 체인은 다음 값을 $?준수하여 계속됩니다.

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

명령이 아닌 파이프라인 연결

파이프라인 체인 연산자는 이름으로 명령이 아닌 파이프라인을 연결하는 데 사용할 수 있습니다. 이는 다른 셸의 동작과 일치하지만 성공을 결정하기가 더 어려워질 수 있습니다.

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

Write-Output 'All done!' 종료되지 않는 오류를 생성한 Test-NotTwo 후 실패한 것으로 간주되므로 실행되지 않습니다.

참고 항목