다음을 통해 공유


about_Parsing

간단한 설명

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

자세한 설명

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

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

Write-Host book

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

참고 항목

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

  • 비효율적입니다. 이렇게 하면 PowerShell이 여러 번 검색됩니다.
  • 이름이 같은 외부 프로그램이 먼저 확인되므로 의도한 cmdlet을 실행할 수 없습니다.
  • Get-HelpGet-Command 사 없는 이름을 인식하지 않습니다.
  • 명령 이름은 예약어 또는 언어 키워드일 수 있습니다. 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.3은 명령줄이 네이티브 명령에 대해 구문 분석되는 방식을 변경했습니다.

주의

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

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

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

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

$PSNativeCommandArgumentPassing 중 하나 Legacy 또는 Standard로 설정된 경우 파서는 이러한 파일을 확인하지 않습니다.

참고 항목

다음 예제에서는 도구를 사용합니다 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

참고 항목