about_Parsing

簡単な説明

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

長い説明

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

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

Write-Host book

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

注意

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

  • 非効率的です。 これにより、PowerShell が複数回検索されます。
  • 同じ名前の外部プログラムが最初に解決されるため、目的のコマンドレットを実行できない場合があります。
  • Get-Help 動詞 Get-Command のない名前を認識しません。
  • コマンド名には、予約語または言語キーワードを指定できます。 Process は両方であり、解決されません Get-Process

式モード

式モードは、スクリプト言語での値の操作に必要な式を組み合わせることを目的としています。 式は PowerShell 構文の値の表現であり、単純または複合にすることができます。次に例を示します。

リテラル式は、その値を直接表現します。

'hello'
32

変数式は、参照する変数の値を保持します。

$x
$script:path

演算子は、評価のために他の式を組み合わせます。

-12
-not $Quiet
3 + 7
$input.Length -gt 1
  • 文字列リテラルは 引用符で囲む必要があります。
  • 数値 は、(エスケープされない限り) 一連の文字としてではなく数値として扱われます。
  • 演算子 は、単項演算子 (like、-not二項演算子など-gt``-``+) を含め、演算子として解釈され、それぞれの演算が引数 (オペランド) に適用されます。
  • 属性式と変換式 は式として解析され、下位の式 (例: [int] '7'.
  • 変数参照 は値に対して評価されますが、 スプラッティング (つまり、事前に入力されたパラメーター セットを貼り付ける) は禁止され、パーサー エラーが発生します。
  • それ以外の場合は、呼び出されるコマンドとして扱われます。

引数モード

解析時に、PowerShell は最初に入力を式として解釈します。 ただし、コマンド呼び出しが発生した場合、解析は引数モードで続行されます。 パスなどのスペースを含む引数がある場合は、それらの引数値を引用符で囲む必要があります。

引数モードは、シェル環境のコマンドの引数とパラメーターを解析するために設計されています。 次のいずれかの構文を使用しない限り、すべての入力は展開可能な文字列として扱われます。

  • ドル記号 ($) の後に変数名が続いて変数参照が開始されます。それ以外の場合は、展開可能な文字列の一部として解釈されます。 変数参照には、メンバー アクセスまたはインデックス作成を含めることができます。

    • たとえば $HOME、単純な変数参照に続く追加の文字は、同じ引数の一部と見なされます。 変数名を中かっこ ({}) で囲んで、後続の文字から区切ります。 たとえば、「 ${HOME} 」のように入力します。
    • 変数参照にメンバー アクセスが含まれている場合、追加の文字の先頭は新しい引数の先頭と見なされます。 たとえば、 $HOME.Length-more 2 つの引数 (値の $HOME.Length リテラルと文字列リテラル) が返されます -more
  • 引用符 (' および ") の開始文字列

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

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

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

  • 部分式演算子 ($()) が埋め込み式を開始する

  • 先頭記号 (@) は、スプラッティング ()、配列 ()、ハッシュ テーブル リテラル (@(1,2,3)``@args``@{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" (文字列)
Write-Output(2+2) Expression 4 (整数)
$a Expression 4 (整数)
Write-Output $a Expression 4 (整数)
$a+2 Expression 6 (整数)
Write-Output $a+2 引数 "4+2" (文字列)
$- 引数 "$-" (コマンド)
Write-Output $- 引数 "$-" (文字列)
a$a Expression "a$a" (コマンド)
Write-Output a$a 引数 "a4" (文字列)
a'$a' Expression "a$a" (コマンド)
Write-Output a'$a' 引数 "a$a" (文字列)
a"$a" Expression "a$a" (コマンド)
Write-Output a"$a" 引数 "a4" (文字列)
a$(2) Expression "a$(2)" (コマンド)
Write-Output a$(2) 引数 "a2" (文字列)

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

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

ネイティブ コマンドに引数を渡す

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 は行内の残りの文字をリテラルとして扱います。 それが実行する唯一の解釈は、標準の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> 、トークンはそのまま渡されます。

ストリーム リダイレクト (like >file.txt) は、ターゲット コマンドに引数として逐語的に渡されるため、使用できません。

引用符文字を含む引数の受け渡し

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

注意

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

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

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

echoargs パラメーターTestExeは、実行可能ファイルの引数として受け取った値を表示します。 このツールを使用して、引数内の文字が正しくエスケープされていることを確認できます。

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 --% """C:\Program Files (x86)\Microsoft\\""
TestExe -echoargs --% """%ProgramFiles(x86)%\Microsoft\\""

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

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

ソース コードからビルド TestExe できます。 TestExe を参照してください。

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>

試験的な機能

Powershell 7.2 には、 PSNativeCommandArgumentPassing の試験的機能が含まれています。 この試験段階の機能が有効になっている場合、PowerShell は、ネイティブ実行可能ファイルを呼び出すときにStartProcessInfo文字列を再構築する現在のメカニズムではなく、オブジェクトの ArgumentList プロパティを使用します。

詳細については、「 PSNativeCommandArgumentPassing」を参照してください。

こちらもご覧ください