PowerShell 연산자 우선순위
PowerShell 연산자 우선순위 (about_Operator_Precedence)
한 식 안에 연산자가 여러 개 들어가면, PowerShell은 어떤 순서로 계산할까요? 이 주제는 PowerShell이 연산자를 우선순위 순서대로 정리한 목록이에요. 우선순위가 같으면 식에 등장한 순서대로 왼쪽에서 오른쪽으로 평가돼요. 다만 예외가 있어요. 할당 연산자, 캐스트 연산자, 부정 연산자(!, -not, -bnot)는 반대로 오른쪽에서 왼쪽으로 평가합니다. 그리고 괄호 같은 묶음 기호를 쓰면 기본 우선순위를 무시하고, 괄호 안 부분을 먼저 계산하도록 강제할 수 있어요.
출처: about_Operator_Precedence (Microsoft Learn, PowerShell 7.6)
본문
아래 목록은 평가되는 순서대로 연산자들을 나열한 거예요. 같은 줄에 있거나 같은 그룹에 있는 연산자는 우선순위가 같아요. Operator 열에는 연산자가, Reference 열에는 해당 연산자를 설명하는 도움말 항목이 들어 있어요. 항목을 직접 열어 보려면 Get-Help -Name <topic-name>을 쓰면 됩니다.
| 연산자 | 참고 항목 |
|---|---|
$() @() () @{} |
about_Operators |
. ?. (멤버 접근) |
about_Operators |
:: (정적) |
about_Operators |
[0] ?[0] (인덱스 연산자) |
about_Operators |
[int] (캐스트 연산자) |
about_Operators |
-split (단항) |
about_Split |
-join (단항) |
about_Join |
, (쉼표 연산자) |
about_Operators |
++ -- |
about_Assignment_Operators |
! -not |
about_Logical_Operators |
.. (범위 연산자) |
about_Operators |
-f (형식 연산자) |
about_Operators |
- (단항/음수) |
about_Arithmetic_Operators |
* / % |
about_Arithmetic_Operators |
+ - |
about_Arithmetic_Operators |
다음 그룹의 연산자들은 우선순위가 같아요. 대소문자 구분 변형과 명시적 대소문자 무시 변형도 같은 우선순위를 가집니다.
| 연산자 | 참고 항목 |
|---|---|
-split (이항) |
about_Split |
-join (이항) |
about_Join |
-is -isnot -as |
about_Type_Operators |
-eq -ne -gt -ge -lt -le |
about_Comparison_Operators |
-like -notlike |
about_Comparison_Operators |
-match -notmatch |
about_Comparison_Operators |
-in -notIn |
about_Comparison_Operators |
-contains -notcontains |
about_Comparison_Operators |
-replace |
about_Comparison_Operators |
여기부터는 다시 연산자들이 우선순위 순서대로 이어집니다.
| 연산자 | 참고 항목 |
|---|---|
-band -bnot -bor -bxor -shr -shl |
about_Arithmetic_Operators |
-and -or -xor |
about_Logical_Operators |
다음 항목들은 진짜 연산자가 아니에요. 식 문법이 아니라 PowerShell의 명령 구문에 속하는 부분이죠. 할당은 언제나 마지막에 일어나는 동작입니다.
| 구문 | 참고 항목 |
|---|---|
. (닷-소스) |
about_Operators |
& (호출) |
about_Operators |
? <참이면> : <거짓이면> (삼항 연산자) |
about_Operators |
?? (null 병합 연산자) |
about_Operators |
| ` | ` (파이프라인 연산자) |
> >> 2> 2>> 2>&1 |
about_Redirection |
| `&& | |
= += -= *= /= %= ??= |
about_Assignment_Operators |
예시
아래 두 예시는 산술 연산자와, 괄호로 묶인 부분을 먼저 계산하도록 강제했을 때의 효과를 보여줘요.
PS> 2 + 3 * 4 14 PS> (2 + 3) * 4 20
다음 예시는 현재 디렉터리에서 읽기 전용 텍스트 파일을 가져와 $readOnly 변수에 저장해요.
$readOnly = Get-ChildItem -Path *.txt | Where-Object { $_.IsReadOnly }
이 예시는 다음 예시와 같은 의미예요.
$readOnly = (Get-ChildItem -Path *.txt | Where-Object { $_.IsReadOnly })
왜 같은 걸까요? 파이프라인 연산자(|)가 할당 연산자(=)보다 우선순위가 높아서, Get-ChildItem이 가져온 파일들이 $readOnly 변수에 할당되기 전에 먼저 Where-Object로 보내져 필터링되기 때문이에요.
다음 예시는 인덱스 연산자가 캐스트 연산자보다 우선한다는 걸 보여줍니다.
이 식은 문자열 세 개로 이루어진 배열을 만들어요. 그다음 인덱스 연산자에 0을 써서 배열의 첫 번째 객체(첫 번째 문자열)를 고르고, 마지막으로 선택된 객체를 문자열로 캐스트하죠. 이 경우 캐스트는 아무 효과가 없어요.
PS> [string]@('Windows','PowerShell','2.0')[0] Windows
이번엔 괄호를 써서 캐스트가 인덱스 선택보다 먼저 일어나도록 강제해요. 그 결과 전체 배열이 (하나의) 문자열로 캐스트됩니다. 그다음 인덱스 연산자가 그 문자열 배열의 첫 번째 항목, 즉 첫 글자를 고르는 거죠.
PS> ([string]@('Windows','PowerShell','2.0'))[0] W
다음 예시에서는 -gt(크다) 연산자가 -and(논리 AND) 연산자보다 우선순위가 높기 때문에, 식의 결과는 FALSE예요.
PS> 2 -gt 4 -and 1 False
이것은 다음 식과 같아요.
PS> (2 -gt 4) -and 1 False
만약 -and 연산자가 더 높은 우선순위였다면 결과는 TRUE였을 거예요.
PS> 2 -gt (4 -and 1) True
그런데 이 예시는 연산자 우선순위를 다루는 데 있어 중요한 원칙을 보여주기도 해요. 식을 사람이 해석하기 어려울 때는, 기본 우선순위를 어기더라도 괄호로 평가 순서를 강제하라는 거예요. 괄호는 스크립트를 읽고 유지보수하는 사람에게 당신의 의도를 분명히 전달해 주니까요.
다음 예시는 -and와 -or 논리 연산자 사이의 우선순위를 보여줘요.
PS> $true -or $false -and $false False
C# 같은 다른 언어에서는 논리 AND가 논리 OR보다 우선순위가 높은 게 보통이라서, 위 식이 TRUE가 되리라 기대할 수 있어요. 그런데 PowerShell에서 -and와 -or 연산자는 우선순위가 같아요. 식에 등장한 순서대로 왼쪽에서 오른쪽으로 평가됩니다. $true -or $false는 TRUE이고 $true -and $false는 FALSE이므로, 전체 식의 결과는 FALSE예요.
중요: WMI 쿼리 언어(WQL)나 Active Directory 필터처럼 PowerShell 안의 다른 문맥은 각자 서로 다른 연산자 우선순위를 가질 수 있어요. PowerShell 논리 연산자의 우선순위와 다를 수 있으니 참고하세요.