다음을 통해 공유


about_Parsing

간단한 설명

PowerShell에서 명령을 구문 분석하는 방법을 설명합니다.

자세한 설명

명령 프롬프트에 명령을 입력하면 PowerShell은 명령 텍스트를 토큰이라는 일련의 세그먼트로 나눕니다. 그런 다음 각 토큰을 해석하는 방법을 결정합니다.

예를 들어 다음을 입력하는 경우

Write-Host book

PowerShell은 명령을 두 개의 토큰 Write-Host 으로 분할하고 식 모드 및 book인수 모드의 두 가지 주요 구문 분석 모드 중 하나를 사용하여 각 토큰을 독립적으로 해석합니다.

참고 항목

PowerShell은 명령 입력을 구문 분석할 때 명령 이름을 cmdlet 또는 네이티브 실행 파일로 확인하려고 시도합니다. 명령 이름에 정확히 일치하는 항목이 없으면 PowerShell이 명령 앞에 기본 동사로 추가됩니다 Get- . 예를 들어 PowerShell은 .로 Get-Service구문 분석합니다Service. 다음과 같은 이유로 이 기능을 사용하지 않는 것이 좋습니다.

  • 비효율적입니다. 이렇게 하면 PowerShell이 여러 번 검색됩니다.
  • 이름이 같은 외부 프로그램이 먼저 확인되므로 의도한 cmdlet을 실행할 수 없습니다.
  • Get-HelpGet-Command 사 없는 이름을 인식하지 않습니다.
  • 명령 이름은 예약어 또는 언어 키워드(keyword) 수 있습니다. Process 은 둘 다이며 확인할 수 Get-Process없습니다.

식 모드

식 모드는 스크립팅 언어의 값 조작에 필요한 식을 결합하기 위한 것입니다. 식은 PowerShell 구문의 값 표현이며 단순하거나 복합적일 수 있습니다. 예를 들면 다음과 같습니다.

리터럴 식은 해당 값의 직접 표현입니다.

'hello'
32

변수 식은 참조하는 변수의 값을 전달합니다.

$x
$script:path

연산자는 평가를 위해 다른 식을 결합합니다.

-12
-not $Quiet
3 + 7
$input.Length -gt 1
  • 문자열 리터럴은 따옴표로 묶어야 합니다.
  • 숫자는 일련의 문자가 아닌 숫자 값으로 처리됩니다(이스케이프되지 않는 한).
  • 단항 연산자 및 이진 연산자 등 --not 과 같은 +-gt연산자는 연산자로 해석되고 해당 인수(피연산자)에 해당 연산을 적용합니다.
  • 특성 및 변환 식은 식으로 구문 분석되고 하위 식에 적용됩니다. 예: [int] '7'
  • 변수 참조는 해당 값으로 평가되지만 스플래팅 은 금지되어 파서 오류가 발생합니다.
  • 다른 항목은 호출할 명령으로 처리됩니다.

인수 모드

구문 분석할 때 PowerShell은 먼저 입력을 식으로 해석하려고 합니다. 그러나 명령 호출이 발생하면 인수 모드에서 구문 분석이 계속됩니다. 경로와 같은 공백이 포함된 인수가 있는 경우 해당 인수 값을 따옴표로 묶어야 합니다.

인수 모드는 셸 환경에서 명령에 대한 인수 및 매개 변수를 구문 분석하기 위해 설계되었습니다. 다음 구문 중 하나를 사용하지 않는 한 모든 입력은 확장 가능한 문자열로 처리됩니다.

  • 달러 기호($)와 변수 이름이 뒤에 오면 변수 참조가 시작되고, 그렇지 않으면 확장 가능한 문자열의 일부로 해석됩니다. 변수 참조에는 멤버 액세스 또는 인덱싱이 포함될 수 있습니다.

    • 같은 간단한 변수 참조를 $HOME따르는 추가 문자는 동일한 인수의 일부로 간주됩니다. 변수 이름을 중괄호({})로 묶어 후속 문자와 구분합니다. 예들 들어 ${HOME}입니다.
    • 변수 참조에 멤버 액세스가 포함된 경우 추가 문자 중 첫 번째 문자는 새 인수의 시작으로 간주됩니다. 예를 들어 $HOME.Length-more 두 개의 인수인 값과 문자열 리터럴이 $HOME.Length 생성됩니다 -more.
  • 따옴표('") 시작 문자열

  • 중괄호({})가 새 스크립트 블록을 시작합니다.

  • 호출되는 명령이 네이티브 애플리케이션이 아닌 한 쉼표(,)는 배열로 전달된 목록을 도입합니다. 이 경우 확장 가능한 문자열의 일부로 해석됩니다. 초기, 연속 또는 후행 쉼표는 지원되지 않습니다.

  • 괄호(())가 새 식을 시작합니다.

  • 하위 식 연산자($())가 포함된 식을 시작합니다.

  • 초기 기호(@)는 스플래팅(), 배열(@args) 및 해시 테이블 리터럴(@(1,2,3)@{a=1;b=2})과 같은 식 구문을 시작합니다.

  • (), $()@() 토큰의 시작 부분에 식 또는 중첩된 명령을 포함할 수 있는 새 구문 분석 컨텍스트를 만듭니다.

    • 뒤에 추가 문자가 추가되면 첫 번째 추가 문자는 별도의 새 인수의 시작으로 간주됩니다.
    • 앞에 따옴표가 없는 리터럴 $() 이 확장 가능한 문자열 () 처럼 작동하면 식인 새 인수를 시작하고 식 @() 인 새 인수를 시작하여 리터럴 @() 로 사용합니다.
  • 이스케이프가 여전히 필요한 메타 문자는 제외하고 다른 모든 항목은 확장 가능한 문자열로 처리됩니다. 특수 문자 처리를 참조 하세요.

    • 인수 모드 메타 문자(특수 구문 의미가 있는 문자)는 다음과 <space> ' " ` , ; ( ) { } | & < > @ #같습니다. 이 < > @ # 중 토큰이 시작될 때만 특별합니다.
  • 중지 구문 분석 토큰(--%)은 모든 다시 기본 인수의 해석을 변경합니다. 자세한 내용은 아래의 토큰 구문 분석 중지 섹션을 참조하세요.

예제

다음 표에서는 식 모드 및 인수 모드에서 처리되는 토큰과 해당 토큰의 평가에 대한 몇 가지 예제를 제공합니다. 이러한 예제의 경우 변수 $a 값은 .입니다 4.

예시 모드 결과
2 2(정수)
`2 "2"(명령)
Write-Output 2 2(정수)
2+2 4(정수)
Write-Output 2+2 인수 "2+2"(문자열)
Write-Output(2+2) 4(정수)
$a 4(정수)
Write-Output $a 4(정수)
$a+2 6(정수)
Write-Output $a+2 인수 "4+2"(문자열)
$- 인수 "$-"(명령)
Write-Output $- 인수 "$-"(문자열)
a$a "a$a"(명령)
Write-Output a$a 인수 "a4"(문자열)
a'$a' "a$a"(명령)
Write-Output a'$a' 인수 "a$a"(문자열)
a"$a" "a$a"(명령)
Write-Output a"$a" 인수 "a4"(문자열)
a$(2) "a$(2)"(명령)
Write-Output a$(2) 인수 "a2"(문자열)

모든 토큰은 부울 또는 문자열과 같은 일종의 개체 형식으로 해석될 수 있습니다. PowerShell은 식에서 개체 형식을 확인하려고 시도합니다. 개체 형식은 명령이 예상하는 매개 변수의 형식과 PowerShell에서 인수를 올바른 형식으로 변환하는 방법을 알고 있는지에 따라 달라집니다. 다음 표에서는 식에서 반환된 값에 할당된 형식의 몇 가지 예를 보여 줍니다.

예시 모드 결과
Write-Output !1 argument "!1"(문자열)
Write-Output (!1) False(부울)
Write-Output (2) 2(정수)
Set-Variable AB A,B argument 'A','B'(배열)
CMD /CECHO A,B argument 'A,B'(문자열)
CMD /CECHO $AB 'A B'(배열)
CMD /CECHO :$AB argument ':A B'(문자열)

특수 문자 처리

백틱 문자(`)는 식의 특수 문자를 이스케이프하는 데 사용할 수 있습니다. 메타문자가 아닌 리터럴 문자로 사용하려는 인수 모드 메타문자를 이스케이프하는 데 가장 유용합니다. 예를 들어 달러 기호($)를 확장 가능한 문자열에서 리터럴로 사용하려면 다음을 수행합니다.

"The value of `$ErrorActionPreference is '$ErrorActionPreference'."
The value of $ErrorActionPreference is 'Continue'.

줄 연속

다음 줄에서 입력을 계속할 수 있도록 줄 끝에 백틱 문자를 사용할 수도 있습니다. 이렇게 하면 이름 및 인수 값이 긴 여러 매개 변수를 사용하는 명령의 가독성이 향상됩니다. 예시:

New-AzVm `
    -ResourceGroupName "myResourceGroupVM" `
    -Name "myVM" `
    -Location "EastUS" `
    -VirtualNetworkName "myVnet" `
    -SubnetName "mySubnet" `
    -SecurityGroupName "myNetworkSecurityGroup" `
    -PublicIpAddressName "myPublicIpAddress" `
    -Credential $cred

그러나 줄 연속을 사용하지 않아야 합니다.

  • 백틱 문자는 보기 어렵고 잊기 쉬울 수 있습니다.
  • 백틱 후 추가 공간이 줄 연속을 중단합니다. 공간을 확인하기 어렵기 때문에 오류를 찾기 어려울 수 있습니다.

PowerShell은 구문의 자연점에서 여러 가지 방법으로 줄 바꿈을 제공합니다.

  • 후 파이프 문자(|)
  • 이진 연산자 후(+, -, -eq등)
  • 배열의 후 쉼표(,)
  • 와 같은 [{문자를 연 후(

큰 매개 변수 집합의 경우 스플래팅을 대신 사용합니다. 예시:

$parameters = @{
    ResourceGroupName = "myResourceGroupVM"
    Name = "myVM"
    Location = "EastUS"
    VirtualNetworkName = "myVnet"
    SubnetName = "mySubnet"
    SecurityGroupName = "myNetworkSecurityGroup"
    PublicIpAddressName = "myPublicIpAddress"
    Credential = $cred
}
New-AzVm @parameters

네이티브 명령에 인수 전달

PowerShell에서 네이티브 명령을 실행할 때 인수는 먼저 PowerShell에서 구문 분석됩니다. 구문 분석된 인수는 각 매개 변수를 공백으로 구분하여 단일 문자열로 조인합니다.

예를 들어 다음 명령은 프로그램을 호출합니다 icacls.exe .

icacls X:\VMS /grant Dom\HVAdmin:(CI)(OI)F

PowerShell 2.0에서 이 명령을 실행하려면 이스케이프 문자를 사용하여 PowerShell이 괄호를 잘못 해석하지 못하도록 해야 합니다.

icacls X:\VMS /grant Dom\HVAdmin:`(CI`)`(OI`)F

중지 구문 분석 토큰

PowerShell 3.0부터는 중지 구문 분석(--%) 토큰을 사용하여 PowerShell이 PowerShell 명령 또는 식으로 입력을 해석하지 못하도록 할 수 있습니다.

참고 항목

중지 구문 분석 토큰은 Windows 플랫폼에서 네이티브 명령을 사용하기 위한 것입니다.

네이티브 명령을 호출할 때 프로그램 인수 앞에 중지 구문 분석 토큰을 배치합니다. 이 기술은 잘못된 해석을 방지하기 위해 이스케이프 문자를 사용하는 것보다 훨씬 쉽습니다.

중지 구문 분석 토큰이 발견되면 PowerShell은 줄의 다시 기본 문자를 리터럴로 처리합니다. 이 함수가 수행하는 유일한 해석은 표준 Windows 표기법을 사용하는 환경 변수의 값(예: %USERPROFILE%.)을 대체하는 것입니다.

icacls X:\VMS --% /grant Dom\HVAdmin:(CI)(OI)F

PowerShell은 다음 명령 문자열을 icacls.exe 프로그램에 보냅니다.

X:\VMS /grant Dom\HVAdmin:(CI)(OI)F

중지 구문 분석 토큰은 다음 줄 바꿈 또는 파이프라인 문자까지만 유효합니다. 줄 연속 문자(`)를 사용하여 효과를 확장하거나 명령 구분 기호(;)를 사용하여 효과를 종료할 수 없습니다.

%variable% 환경 변수 참조 외에는 명령에 다른 동적 요소를 포함할 수 없습니다. % 일괄 처리 파일 내에서 수행할 수 있는 방법으로 문자를 %%이스케이프하는 것은 지원되지 않습니다. %<name>% 토큰은 변함없이 확장됩니다. <name> 정의된 환경 변수를 참조하지 않으면 토큰이 있는 그대로 전달됩니다.

스트림 리디렉션은 대상 명령에 인수로 축자로 전달되므로(예: >file.txt) 사용할 수 없습니다.

다음 예제에서 첫 번째 단계는 중지 구문 분석 토큰을 사용하지 않고 명령을 실행합니다. PowerShell은 따옴표 붙은 문자열을 평가하고 값(따옴표 없음)을 전달하여 cmd.exe오류가 발생합니다.

PS> cmd /c echo "a|b"
'b' is not recognized as an internal or external command,
operable program or batch file.
PS> cmd /c --% echo "a|b"
"a|b"

참고 항목

PowerShell cmdlet을 사용할 때는 중지 구문 분석 토큰이 필요하지 않습니다. 그러나 이러한 인수를 사용하여 네이티브 명령을 호출하도록 설계된 PowerShell 함수에 인수를 전달하는 것이 유용할 수 있습니다.

따옴표 문자가 포함된 인수 전달

일부 네이티브 명령에는 따옴표 문자가 포함된 인수가 사용됩니다. PowerShell 7.2에는 명령줄이 네이티브 명령에 대해 구문 분석되는 방식을 변경하는 PSNativeCommandArgumentPassing 실험적 기능이 포함되어 있습니다. 자세한 내용은 실험적 기능 사용을 참조 하세요.

주의

새 동작은 Window PowerShell 5.1 동작의 호환성이 손상되는 변경 입니다. 새로운 동작은 네이티브 애플리케이션을 호출할 때 발생하는 다양한 문제를 해결하는 스크립트와 자동화를 손상할 수 있습니다. 필요할 때 네이티브 인수 전달을 방지하려면 중지 구문 분석 토큰(--%) 또는 Start-Process cmdlet을 사용합니다.

$PSNativeCommandArgumentPassing 기본 설정 변수는 이 동작을 제어합니다. 이 변수를 사용하면 런타임에 동작을 선택할 수 있습니다. 유효한 값은 Legacy, StandardWindows. 기본 동작은 플랫폼별로 다릅니다. Windows 플랫폼에서는 기본 설정이고 Windows 플랫폼이 아닌 플랫폼은 기본값입니다 WindowsStandard.

Legacy 는 역사적인 동작입니다. 모드에서는 Windows 다음 파일의 Windows 호출에서 자동으로 스타일 인수 전달을 사용하는 경우를 제외하고 모드의 동작과 Standard 모드는 Legacy 동일합니다.

  • cmd.exe
  • cscript.exe
  • wscript.exe
  • .bat로 끝남
  • .cmd로 끝남
  • .js로 끝남
  • .vbs로 끝남
  • .wsf로 끝남

파서가 $PSNativeCommandArgumentPassingLegacyStandard이러한 파일에 대해 검사 않습니다.

참고 항목

다음 예제에서는 도구를 사용합니다 TestExe.exe . 소스 코드에서 빌드 TestExe 할 수 있습니다. PowerShell 원본 리포지토리에서 TestExe를 참조하세요.

이 변경으로 사용할 수 있는 새 동작:

  • 따옴표가 포함된 리터럴 또는 확장 가능한 문자열은 이제 다음과 같이 유지됩니다.

    PS> $a = 'a" "b'
    PS> TestExe -echoargs $a 'c" "d' e" "f
    Arg 0 is <a" "b>
    Arg 1 is <c" "d>
    Arg 2 is <e f>
    
  • 인수로 사용되는 빈 문자열은 이제 유지됩니다.

    PS> TestExe -echoargs '' a b ''
    Arg 0 is <>
    Arg 1 is <a>
    Arg 2 is <b>
    Arg 3 is <>
    

이러한 예제의 목표는 디렉터리 경로(공백 및 따옴표 포함) "C:\Program Files (x86)\Microsoft\" 를 네이티브 명령에 전달하여 경로를 따옴표 붙은 문자열로 수신하는 것입니다.

또는 Standard 모드에서 Windows 다음 예제는 예상된 결과를 생성합니다.

TestExe -echoargs """${env:ProgramFiles(x86)}\Microsoft\"""
TestExe -echoargs '"C:\Program Files (x86)\Microsoft\"'

모드에서 Legacy 동일한 결과를 얻으려면 따옴표를 이스케이프하거나 중지 구문 분석 토큰()--%을 사용해야 합니다.

TestExe -echoargs """""${env:ProgramFiles(x86)}\Microsoft\\"""""
TestExe -echoargs "\""C:\Program Files (x86)\Microsoft\\"""
TestExe -echoargs --% ""\""C:\Program Files (x86)\Microsoft\\"\"""
TestExe -echoargs --% """C:\Program Files (x86)\Microsoft\\""
TestExe -echoargs --% """%ProgramFiles(x86)%\Microsoft\\""

참고 항목

백슬래시(\) 문자는 PowerShell에서 이스케이프 문자로 인식되지 않습니다. ProcessStartInfo.ArgumentList의 기본 API 에서 사용하는 이스케이프 문자입니다.

PowerShell 7.3에는 네이티브 명령에 대한 매개 변수 바인딩을 추적하는 기능도 추가되었습니다. 자세한 내용은 Trace-Command를 참조 하세요.

PowerShell 명령에 인수 전달

PowerShell 3.0부터 매개 변수 끝 토큰(--)을 사용하여 PowerShell이 입력을 PowerShell 매개 변수로 해석하지 못하도록 할 수 있습니다. POSIX 셸 및 유틸리티 사양에 지정된 규칙입니다.

매개 변수 끝 토큰

매개 변수 끝 토큰(--)은 다음에 있는 모든 인수가 큰따옴표가 있는 것처럼 실제 형식으로 전달되어야 임을 나타냅니다. 예를 들어 따옴표를 사용 -- 하거나 매개 변수로 해석하지 않고 문자열 -InputObject 을 출력할 수 있습니다.

Write-Output -- -InputObject
-InputObject

중지 구문 분석(--%) 토큰과 달리 토큰 다음의 -- 모든 값은 PowerShell에서 식으로 해석될 수 있습니다.

Write-Output -- -InputObject $env:PROCESSOR_ARCHITECTURE
-InputObject
AMD64

이 동작은 PowerShell 명령에만 적용됩니다. 외부 명령을 -- 호출할 때 토큰을 사용하는 -- 경우 문자열은 해당 명령에 인수로 전달됩니다.

TestExe -echoargs -a -b -- -c

출력은 인수로 TestExe전달되는 것을 -- 보여줍니다.

Arg 0 is <-a>
Arg 1 is <-b>
Arg 2 is <-->
Arg 3 is <-c>

Tilde (~)

타일드 문자(~)는 PowerShell에서 특별한 의미를 줍니다. 경로의 시작 부분에서 PowerShell 명령과 함께 사용되는 경우 타일 문자가 사용자의 홈 디렉터리로 확장됩니다. 타일드 문자가 경로의 다른 곳에서 사용되는 경우 리터럴 문자로 처리됩니다.

PS D:\temp> $PWD

Path
----
D:\temp

PS D:\temp> Set-Location ~
PS C:\Users\user2> $PWD

Path
----
C:\Users\user2

이 예제 에서는 Name 매개 변수에 New-Item 문자열이 필요합니다. 타일드 문자는 리터럴 문자로 처리됩니다. 새로 만든 디렉터리로 변경하려면 경로를 타일드 문자로 한정해야 합니다.

PS D:\temp> Set-Location ~
PS C:\Users\user2> New-Item -Type Directory -Name ~

    Directory: C:\Users\user2

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----            5/6/2024  2:08 PM                ~

PS C:\Users\user2> Set-Location ~
PS C:\Users\user2> Set-Location .\~
PS C:\Users\user2\~> $PWD

Path
----
C:\Users\user2\~

네이티브 명령과 함께 타일드 문자를 사용하는 경우 PowerShell은 타일을 리터럴 문자로 전달합니다. 경로에 타일을 사용하면 타일 문자를 지원하지 않는 Windows의 네이티브 명령에 오류가 발생합니다.

PS D:\temp> $PWD

Path
----
D:\temp

PS D:\temp> Get-Item ~\repocache.clixml

    Directory: C:\Users\user2

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---           4/29/2024  3:42 PM          88177 repocache.clixml

PS D:\temp> more.com ~\repocache.clixml
Cannot access file D:\temp\~\repocache.clixml

참고 항목