PowerShell 인용 규칙
PowerShell 인용 규칙 (Quoting Rules)
PowerShell에서 문자열을 만들 때 따옴표를 어떻게 써야 하는지가 헷갈릴 때가 많죠. 작은따옴표(')와 큰따옴표(")는 겉보기에는 비슷하지만, PowerShell이 문자열을 해석하는 방식이 완전히 달라요. 이 문서에서는 두 따옴표의 차이, 여기 문자열(here-string), 그리고 문자열 안에 따옴표를 넣는 방법까지 하나씩 짚어볼게요.
출처: about_Quoting_Rules (Microsoft Learn, PowerShell 공식 문서)
본문
짧은 설명
PowerShell에서 단일 인용 부호(작은따옴표)와 이중 인용 부호(큰따옴표)를 사용하는 규칙을 설명하는 문서예요.
자세한 설명
파싱할 때 PowerShell은 먼저 입력을 식(expression)으로 해석하려고 해요. 그런데 명령 호출을 만나면 파싱은 인수 모드(argument mode)로 계속 진행돼요. 따옴표로 묶지 않은 숫자 아닌 인수는 문자열로 취급돼요. 경로처럼 공백이 포함된 인수가 있다면 그 인수 값을 반드시 따옴표로 묶어야 해요. 인수 파싱에 대한 자세한 내용은 about_Parsing 문서의 Argument mode 섹션을 참고해 주세요.
따옴표는 리터럴 문자열을 지정하는 데 사용돼요. 문자열을 작은따옴표(')로 묶거나 큰따옴표(")로 묶을 수 있어요.
따옴표는 여기 문자열(here-string)을 만드는 데에도 사용돼요. 여기 문자열은 따옴표가 문자 그대로 해석되는 단일 인용 또는 이중 인용 문자열이에요. 여기 문자열은 여러 줄에 걸칠 수 있어요. 여기 문자열의 모든 줄은 따옴표로 묶이지 않았더라도 문자열로 해석돼요.
원격 컴퓨터에 보내는 명령에서는 따옴표가 원격 컴퓨터에서 실행되는 명령의 부분을 정의해요. 원격 세션에서 따옴표는 명령 안의 변수가 로컬 컴퓨터에서 먼저 해석될지, 원격 컴퓨터에서 먼저 해석될지도 결정해요.
참고 — 스마트 따옴표(typographic quotes 또는 curly quotes라고도 불러요)는 PowerShell에서 문자열의 일반적인 따옴표로 취급돼요. 스마트 따옴표로 문자열을 묶는 데는 사용하지 마세요. 스마트 따옴표가 포함된 문자열을 작성할 때는 이 문서의 문자열 안에 따옴표 문자 포함하기 섹션의 지침을 따라 주세요. 스마트 따옴표에 대한 자세한 내용은 위키백과의 영어의 인용 부호 문서 중 Smart Quotes 섹션을 참고하세요.
큰따옴표로 묶인 문자열
큰따옴표로 묶인 문자열은 확장 가능한 문자열(expandable string)이에요. 달러 기호($)가 앞에 붙은 변수 이름은 문자열이 명령에 전달돼 처리되기 전에 변수 값으로 치환돼요.
예를 들어 볼게요.
$i = 5
"The value of $i is $i."
이 명령의 출력은 다음과 같아요.
The value of 5 is 5.
또한 큰따옴표로 묶인 문자열에서는 식이 평가되고 그 결과가 문자열에 삽입돼요. 예를 들어,
"The value of $(2+3) is 5."
이 명령의 출력은 다음과 같아요.
The value of 5 is 5.
확장 가능한 문자열에는 기본 변수 참조만 직접 포함할 수 있어요. 배열 인덱싱이나 멤버 접근을 사용하는 변수 참조는 하위 식(subexpression)으로 묶어야 해요. 예:
"PS version: $($PSVersionTable.PSVersion)"
PS version: 7.6.0-preview.4
문자열에서 변수 이름과 뒤따르는 문자를 구분하려면 변수를 중괄호({})로 묶어요. 변수 이름 뒤에 콜론(:)이 오는 경우에 특히 중요해요. PowerShell은 $와 : 사이의 모든 것을 범위 지정자(scope specifier)로 간주해서, 보통 해석이 실패하게 돼요. 예를 들어 "$HOME: where the heart is."는 오류를 던지지만 "${HOME}: where the heart is."는 의도대로 동작해요.
큰따옴표로 묶인 문자열에서 변수 값의 치환을 막으려면 PowerShell의 이스케이프 문자인 백틱(`)을 사용해요.
다음 예시에서는 첫 번째 $i 변수 앞에 오는 백틱이 PowerShell이 변수 이름을 값으로 바꾸지 못하게 해요. 예:
$i = 5
"The value of `$i is $i."
이 명령의 출력은 다음과 같아요.
The value of $i is 5.
작은따옴표로 묶인 문자열
작은따옴표로 묶인 문자열은 축어적 문자열(verbatim string)이에요. 이 문자열은 입력한 그대로 명령에 전달돼요. 어떤 치환도 수행되지 않아요. 예:
$i = 5
'The value of $i is $i.'
이 명령의 출력은 다음과 같아요.
The value $i is $i.
마찬가지로 작은따옴표로 묶인 문자열의 식은 평가되지 않아요. 문자열 리터럴로 해석돼요. 예:
'The value of $(2+3) is 5.'
이 명령의 출력은 다음과 같아요.
The value of $(2+3) is 5.
문자열 안에 따옴표 문자 포함하기
문자열에 큰따옴표를 나타내려면 전체 문자열을 작은따옴표로 묶어요. 예:
'As they say, "live and learn."'
이 명령의 출력은 다음과 같아요.
As they say, "live and learn."
작은따옴표로 묶인 문자열을 큰따옴표 문자열 안에 묶을 수도 있어요. 예:
"As they say, 'live and learn.'"
이 명령의 출력은 다음과 같아요.
As they say, 'live and learn.'
또는 큰따옴표로 묶인 구절 주위에 큰따옴표를 두 번 적어요. 예:
"As they say, ""live and learn."""
이 명령의 출력은 다음과 같아요.
As they say, "live and learn."
작은따옴표로 묶인 문자열 안에 작은따옴표를 포함하려면 작은따옴표를 연달아 두 개 사용해요. 예:
'don''t'
이 명령의 출력은 다음과 같아요.
don't
PowerShell이 큰따옴표를 문자 그대로 해석하도록 하려면 백틱 문자를 사용해요. 그러면 PowerShell이 그 따옴표를 문자열 구분자로 해석하지 않아요. 예:
"Use a quotation mark (`") to begin a string."
'Use a quotation mark (`") to begin a string.'
작은따옴표로 묶인 문자열의 내용은 문자 그대로 해석되기 때문에 백틱 문자는 리터럴 문자로 취급되어 출력에 그대로 표시돼요.
Use a quotation mark (") to begin a string.
Use a quotation mark (`") to begin a string.
PowerShell이 ‘, ’, “, ” 같은 스마트 따옴표를 일반 따옴표로 해석하기 때문에 스마트 따옴표도 이스케이프해야 해요. 예:
"Double ““smart quotation marks`” must be escaped in a double-quoted string."
'Single ‘‘smart quotation marks’’ must be escaped in a single-quoted string.'
Double “smart quotation marks” must be escaped in a double-quoted string.
Single ‘smart quotation marks’ must be escaped in a single-quoted string.
여기 문자열 (Here-strings)
여기 문자열의 인용 규칙은 조금 달라요.
여기 문자열은 골뱅이 기호(@)로 둘러싸인 단일 인용 또는 이중 인용 문자열이에요. 여기 문자열 안의 따옴표는 문자 그대로 해석돼요.
여기 문자열은:
- 여러 줄에 걸치며, 여는 표시 뒤에 줄바꿈이 오고,
- 닫는 표시 앞에 줄바꿈이 오며,
- 여는 표시와 닫는 표시 사이의 모든 줄을 하나의 문자열로 포함해요.
일반 문자열처럼 큰따옴표 여기 문자열에서는 변수가 값으로 치환돼요. 작은따옴표 여기 문자열에서는 변수가 값으로 치환되지 않아요.
여기 문자열은 어떤 텍스트에도 사용할 수 있지만, 특히 다음 종류의 텍스트에 유용해요.
- 리터럴 따옴표를 포함하는 텍스트
- HTML이나 XML 블록 같은 여러 줄의 텍스트
- 스크립트나 함수 문서의 도움말 텍스트
여기 문자열은 다음 두 형식 중 하나를 가질 수 있어요. 여기서 <Enter>는 ENTER 키를 눌렀을 때 추가되는 줄바꿈(숨은 문자)을 나타내요.
큰따옴표:
@"<Enter>
<string> [string] ...<Enter>
"@
작은따옴표:
@'<Enter>
<string> [string] ...<Enter>
'@
참고 — 마지막 줄바꿈 문자는 닫는 표시의 일부예요. 여기 문자열에는 추가되지 않아요.
여기 문자열에는 여는 표시와 닫는 표시 사이의 모든 텍스트가 포함돼요. 여기 문자열에서는 모든 따옴표가 문자 그대로 해석돼요. 예:
@"
For help, type "Get-Help"
"@
이 명령의 출력은 다음과 같아요.
For help, type "Get-Help"
여기 문자열을 사용하면 명령에서 문자열을 다루기가 더 간단해져요. 예:
@"
Use a quotation mark, like ' or ", to begin a string.
"@
이 명령의 출력은 다음과 같아요.
Use a quotation mark, like ' or ", to begin a string.
작은따옴표 여기 문자열에서는 변수가 문자 그대로 해석되고 정확히 그대로 재현돼요. 예:
@'
The $PROFILE variable contains the path
of your PowerShell profile.
'@
이 명령의 출력은 다음과 같아요.
The $PROFILE variable contains the path
of your PowerShell profile.
큰따옴표 여기 문자열에서는 변수가 값으로 치환돼요. 예:
@"
Even if you have not created a profile,
the path of the profile file is:
$PROFILE.
"@
이 명령의 출력은 다음과 같아요.
Even if you have not created a profile,
the path of the profile file is:
C:\Users\User1\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1.
여기 문자열은 보통 여러 줄을 변수에 할당하는 데 사용돼요. 예를 들어 다음 여기 문자열은 XML 한 페이지를 $page 변수에 할당해요.
$page = [xml] @"
<command:command xmlns:maml="http://schemas.microsoft.com/maml/2004/10"
xmlns:command="http://schemas.microsoft.com/maml/dev/command/2004/10"
xmlns:dev="http://schemas.microsoft.com/maml/dev/2004/10">
<command:details>
<command:name>
Format-Table
</command:name>
<maml:description>
<maml:para>Formats the output as a table.</maml:para>
</maml:description>
<command:verb>format</command:verb>
<command:noun>table</command:noun>
<dev:version></dev:version>
</command:details>
...
</command:command>
"@
여기 문자열은 ConvertFrom-StringData cmdlet의 입력 형식으로도 편리해요. 이 cmdlet은 여기 문자열을 해시 테이블로 변환해요. 자세한 내용은 ConvertFrom-StringData를 참고하세요.
참고 — PowerShell은 여기 문자열의
@구문을 사용하지 않고도 큰따옴표나 작은따옴표 문자열이 여러 줄에 걸치도록 허용해요. 하지만 전체 여기 문자열 구문이 권장되는 방식이에요.
확장 가능한 문자열의 해석
확장된 문자열은 콘솔에서 보는 기본 출력과 반드시 같아 보이지는 않아요.
배열을 포함한 컬렉션은 요소의 문자열 표현 사이에 공백 하나를 넣어 문자열로 변환돼요. 다른 구분 기호는 기본 설정 변수 $OFS를 지정해 설정할 수 있어요. 자세한 내용은 $OFS 기본 설정 변수를 참고하세요.
다른 타입의 인스턴스는 ToString() 메서드를 호출해 문자열로 변환되는데, 이 메서드는 의미 있는 표현을 주지 못할 수 있어요. 예:
"hashtable: $(@{ key = 'value' })"
hashtable: System.Collections.Hashtable
콘솔과 같은 출력을 얻으려면 하위 식에서 Out-String으로 파이프해 주세요. 앞뒤의 빈 줄을 제거하려면 Trim() 메서드를 적용해요.
"hashtable:`n$((@{ key = 'value' } | Out-String).Trim())"
hashtable:
Name Value
---- -----
key value
문화권 설정이 문자열 해석에 미치는 영향
ToString() 메서드는 현재 구성된 문화권 설정을 사용해 값을 문자열로 변환해요. 예를 들어 다음 PowerShell 세션의 문화권은 de-DE로 설정돼 있어요. ToString() 메서드가 $x 값을 문자열로 변환할 때 소수 구분 기호로 쉼표(,)를 사용해요. 또한 ToString() 메서드는 날짜를 독일 로캘 설정에 적합한 형식으로 문자열로 변환해요.
PS> Get-Culture
LCID Name DisplayName
---- ---- -----------
1031 de-DE German (Germany)
PS> $x = 1.2
PS> $x.ToString()
1,2
PS> (Get-Date 2024-03-19).ToString()
19.03.2024 00:00:00
하지만 PowerShell은 확장 가능한 문자열 식을 해석할 때 고정 문화권(invariant culture)을 사용해요.
PS? "$x"
1.2
PS> "$(Get-Date 2024-03-19)"
03/19/2024 00:00:00
외부 명령에 따옴표로 묶인 문자열 전달하기
일부 네이티브 명령은 따옴표 문자를 포함하는 인수를 기대해요. PowerShell은 외부 명령에 전달하기 전에 따옴표로 묶인 문자열을 해석해요. 이 해석은 바깥쪽 따옴표 문자를 제거해요.
이 동작에 대한 자세한 내용은 about_Parsing 문서를 참고하세요.
경고 — Windows에서 배치 파일로 인수를 전달할 때 인수는
cmd.exe에 원시 명령줄 문자열로 전달돼요. PowerShell과 기본 API가 매개 변수를 안전하게 해석하려고 시도하지만, 신뢰할 수 없는 입력은 다른 방식으로 전달해야 해요.