about_Parsing

簡単な説明

PowerShell でコマンドを解析する方法について説明します。

長い説明

コマンド プロンプトでコマンドを入力すると、PowerShell はコマンド テキストを トークン と呼ばれる一連のセグメントに分割し、各トークンの解釈方法を決定します。

たとえば、次のように入力します。

Write-Host book

PowerShell は、コマンドを 2 つのトークン と bookに分割し、Write-Host式モードと引数モードの 2 つの主要な解析モードのいずれかを使用して、各トークンを個別に解釈します。

注意

PowerShell はコマンド入力を解析するときに、コマンド名をコマンドレットまたはネイティブ実行可能ファイルに解決しようとします。 コマンド名が完全に一致しない場合、PowerShell はコマンドの Get- 先頭に既定の動詞として付加します。 たとえば、PowerShell では としてGet-Service解析されますService。 次の理由から、この機能を使用することはお勧めしません。

  • 非効率的です。 これにより、PowerShell が複数回検索されます。
  • 同じ名前の外部プログラムが最初に解決されるため、目的のコマンドレットを実行することはできません。
  • 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 と文字列リテラル の 2 つの引数が返されます -more
  • 引用符 (' および ") の開始文字列

  • 中かっこ ({}) が新しいスクリプト ブロックを開始する

  • コンマ (,) は、呼び出されるコマンドがネイティブ アプリケーションでない限り、配列として渡されるリストを導入します。その場合、それらは展開可能な文字列の一部として解釈されます。 最初、連続、または末尾のコンマはサポートされていません。

  • かっこ (()) で新しい式を開始する

  • Subexpression 演算子 ($()) が埋め込み式を開始します

  • 最初のアット マーク (@) は、スプラッティング ()、配列 (@args)、ハッシュ テーブル リテラル (@(1,2,3)@{a=1;b=2}) などの式構文を開始します。

  • ()$()、および @() トークンの開始時に、式または入れ子になったコマンドを含めることができる新しい解析コンテキストが作成されます。

    • その後に追加の文字が続くと、最初の追加文字は、新しい個別の引数の先頭と見なされます。
    • 引用符で囲まれていないリテラル$()が前にある場合は、展開可能な文字列のように動作し、()式である新しい引数を開始し@()、式である新しい引数を開始してリテラル@()として受け取ります。
  • それ以外はすべて、エスケープが必要なメタ文字を除き、展開可能な文字列として扱われます。 特殊文字の処理に関するページを参照してください。

    • 引数モードメタ文字 (特別な構文の意味を持つ文字) は、 です <space> ' " ` , ; ( ) { } | & < > @ #。 そのうち、 < > @ # はトークンの開始時にのみ特別です。
  • 停止解析トークン (--%) は、残りのすべての引数の解釈を変更します。 詳細については、以下の 「stop-parsing token 」セクションを参照してください。

次の表に、式モードと引数モードで処理されるトークンの例と、それらのトークンの評価を示します。 これらの例では、変数 $a の値は です 4

モード 結果
2 2 (整数)
`2 Expression "2" (コマンド)
Write-Output 2 Expression 2 (整数)
2+2 Expression 4 (整数)
Write-Output 2+2 引数 "2+2" (string)
Write-Output(2+2) Expression 4 (整数)
$a Expression 4 (整数)
Write-Output $a Expression 4 (整数)
$a+2 Expression 6 (整数)
Write-Output $a+2 引数 "4+2" (string)
$- 引数 "$-" (コマンド)
Write-Output $- 引数 "$-" (string)
a$a Expression "a$a" (コマンド)
Write-Output a$a 引数 "a4" (string)
a'$a' Expression "a$a" (コマンド)
Write-Output a'$a' 引数 "a$a" (string)
a"$a" Expression "a$a" (コマンド)
Write-Output a"$a" 引数 "a4" (string)
a$(2) Expression "a$(2)" (コマンド)
Write-Output a$(2) 引数 "a2" (string)

すべてのトークンは、 ブール 型や 文字列型など、何らかの種類のオブジェクト型として解釈できます。 PowerShell は、 式からオブジェクトの種類を決定しようとします。 オブジェクトの種類は、コマンドで想定されるパラメーターの型と、引数を正しい型に変換する方法を PowerShell が認識しているかどうかによって異なります。 次の表は、式によって返される値に割り当てられた型のいくつかの例を示しています。

モード 結果
Write-Output !1 引数 "!1" (string)
Write-Output (!1) expression False (ブール値)
Write-Output (2) expression 2 (整数)
Set-Variable AB A,B 引数 'A','B' (配列)
CMD /CECHO A,B 引数 'A,B' (string)
CMD /CECHO $AB expression 'A B' (配列)
CMD /CECHO :$AB 引数 ':A B' (string)

特殊文字の処理

バックティック文字 (`) を使用して、式内の任意の特殊文字をエスケープできます。 これは、メタ文字ではなくリテラル文字として使用する引数モードメタ文字をエスケープする場合に最も便利です。 たとえば、ドル記号 ($) を展開可能な文字列のリテラルとして使用するには、次のようにします。

"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 によって解析されます。 解析された引数は 1 つの文字列に結合され、各パラメーターはスペースで区切られます。

たとえば、次のコマンドはプログラムを 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 は行の残りの文字をリテラルとして扱います。 実行する唯一の解釈は、 などの %USERPROFILE%標準の Windows 表記を使用する環境変数の値を置き換える方法です。

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"

注意

Windows システム上の一部のコマンドは、Windows バッチ ファイルとして実装されます。 たとえば、Azure CLI のその az コマンドは Windows バッチ ファイルです。

引用符文字を含む引数を渡す

一部のネイティブ コマンドでは、引用符文字を含む引数が必要です。 通常、PowerShell のコマンド ライン解析では、指定した引用符文字が削除されます。 解析された引数は 1 つの文字列に結合され、各パラメーターはスペースで区切られます。 この文字列は、オブジェクトの Arguments プロパティに ProcessStartInfo 割り当てられます。 文字列内の引用符は、余分な引用符または円記号 (\) 文字を使用してエスケープする必要があります。

注意

バックスラッシュ (\) 文字は、PowerShell ではエスケープ文字として認識されません。 これは、 の基になる API ProcessStartInfo.Argumentsによって使用されるエスケープ文字です。

エスケープ要件の詳細については、 ProcessStartInfo.Arguments のドキュメントを参照してください。

注意

次の例では、 ツールを TestExe.exe 使用します。 ソース コードからビルド TestExe できます。 PowerShell ソース リポジトリの TestExe に関するページを参照してください。

これらの例の目的は、パスを引用符で囲まれた文字列として受け取るように、ネイティブ コマンドにディレクトリ "C:\Program Files (x86)\Microsoft\" パスを渡すことです。

TestExeechoargs パラメーターは、実行可能ファイルの引数として受け取った値を表示します。 このツールを使用して、引数内の文字を適切にエスケープしたことを確認できます。

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\\""

出力はすべての例で同じです。

Arg 0 is <"C:\Program Files (x86)\Microsoft\">

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>

こちらもご覧ください