次の方法で共有


8. ステートメント

編集メモ

Von Bedeutung

Windows PowerShell 言語仕様 3.0 は、2012 年 12 月に公開され、Windows PowerShell 3.0 に基づいています。 この仕様では、PowerShell の現在の状態は反映されません。 現在の状態を反映するようにこのドキュメントを更新する予定はありません。 このドキュメントは、履歴参照のためにここに示されています。

仕様文書は、Microsoft ダウンロード センターから Microsoft Word 文書として入手できます。https://www.microsoft.com/download/details.aspx?id=36389 Word 文書は、Microsoft Learn でプレゼンテーション用に変換されています。 変換中に、Docs プラットフォームの書式設定に対応するために、いくつかの編集の変更が行われました。 一部の入力ミスと軽微なエラーが修正されました。

8.1 ステートメントブロックとリスト

構文:

ヒント

構文定義の ~opt~ 表記は、構文エンティティが構文で省略可能であることを示します。

statement-block:
    new-lines~opt~ { statement-list~opt~ new-lines~opt~ }

statement-list:
    statement
    statement-list statement

statement:
    if-statement
    label~opt~ labeled-statement
    function-statement
    flow-control-statement statement-terminator
    trap-statement
    try-statement
    data-statement
    inlinescript-statement
    parallel-statement
    sequence-statement
    pipeline statement-terminator

statement-terminator:
    ;
    new-line-character

説明:

ステートメントは、実行される何らかのアクションを指定します。 この句内で特に指定されていない限り、ステートメントは字句の順序で実行されます。

ステートメント ブロックを使用すると、一連のステートメントを 1 つの構文単位にグループ化できます。

8.1.1 ラベル付きステートメント

構文:

labeled-statement:
    switch-statement
    foreach-statement
    for-statement
    while-statement
    do-statement

説明:

反復ステートメント (§8.4) または switch ステートメント (§8.6) は、必要に応じて、1 つのステートメント ラベルである ラベルの直前に置く場合があります。 ステートメント ラベルは、中断 (§8.5.1) または続行 (§8.5.2) ステートメントの省略可能なターゲットとして使用されます。 ただし、ラベルによって制御フローが変更されることはありません。

コロン (:) とその後のトークンの間に空白を使用することはできません。

例:

:go_here while ($j -le 100) {
    # ...
}

:labelA
for ($i = 1; $i -le 5; ++$i) {
    :labelB
    for ($j = 1; $j -le 3; ++$j) {
        :labelC
        for ($k = 1; $k -le 2; ++$k) {
            # ...
        }
    }
}

8.1.2 ステートメント値

ステートメントの値は、パイプラインに書き込む値の累積セットです。 ステートメントが 1 つのスカラー値を書き込む場合、これはステートメントの値です。 ステートメントが複数の値を書き込む場合、ステートメントの値は、制約のない 1 次元配列の要素に格納されている値のセットが、書き込まれた順序で行われます。 次の例を確認してください。

$v = for ($i = 10; $i -le 5; ++$i) { }

ループの繰り返しはなく、パイプラインに書き込まれるものもありません。 ステートメントの値は $null

$v = for ($i = 1; $i -le 5; ++$i) { }

ループは 5 回反復処理されますが、パイプラインに書き込まれることはありません。 ステートメントの値は$null。

$v = for ($i = 1; $i -le 5; ++$i) { $i }

ループは、パイプラインに int 値を書き込むたびに 5 回反復処理 $i。 ステートメントの値は Length 5 の object[] です。

$v = for ($i = 1; $i -le 5; ) { ++$i }

ループは 5 回反復処理されますが、パイプラインに書き込まれることはありません。 ステートメントの値は $null

$v = for ($i = 1; $i -le 5; ) { (++$i) }

ループは、各値がパイプラインに書き込まれると 5 回繰り返されます。 ステートメントの値は Length 5 の object[] です。

$i = 1; $v = while ($i++ -lt 2) { $i }

ループは 1 回反復処理されます。 ステートメントの値は、値 2 の int です。

その他の例を次に示します。

# if $count is not currently defined then define it with int value 10
$count = if ($count -eq $null) { 10 } else { $count }

$i = 1
$v = while ($i -le 5) {
    $i                   # $i is written to the pipeline
    if ($i -band 1) {

        "odd"            # conditionally written to the pipeline

    }

    ++$i                 # not written to the pipeline

}
# $v is object[], Length 8, value 1,"odd",2,3,"odd",4,5,"odd"

8.2 パイプライン ステートメント

構文:

pipeline:
    assignment-expression
    expression redirections~opt~ pipeline-tail~opt~
    command verbatim-command-argument~opt~ pipeline-tail~opt~

assignment-expression:
    expression assignment-operator statement

pipeline-tail:
    | new-lines~opt~ command
    | new-lines~opt~ command pipeline-tail

command:
    command-name command-elements~opt~
    command-invocation-operator command-module~opt~ command-name-expr command-elements~opt~

command-invocation-operator: one of
    &   .

command-module:
    primary-expression

command-name:
    generic-token
    generic-token-with-subexpr

generic-token-with-subexpr:
    No whitespace is allowed between ) and command-name.
    generic-token-with-subexpr-start statement-list~opt~ )

command-namecommand-name-expr:
    command-name

primary-expressioncommand-elements:
    command-element
    command-elements command-element

command-element:
    command-parameter
    command-argument
    redirection

command-argument:
    command-name-expr

verbatim-command-argument:
    --% verbatim-command-argument-chars

説明:

リダイレクトについては、§7.12 で説明されています。assignment-expression§7.11 で説明されています。およびコマンド呼び出し演算子ドット (.) については、§3.5.5 で説明します。 コマンド呼び出しでの引数とパラメーターのマッピングの詳細については、 §8.14 を参照してください。

パイプラインの最初のコマンドは、式またはコマンド呼び出しです。 通常、コマンド呼び出しは コマンド名で始まります。これは通常、ベア識別子です。 command-elements は、コマンドの引数リストを表します。 改行またはエスケープされていないセミコロンがパイプラインを終了します。

コマンド呼び出しは、コマンドの名前の後に 0 個以上の引数が続きます。 引数を管理する規則は次のとおりです。

  • 式ではないが、エスケープされていない空白のない任意のテキストを含む引数は、二重引用符で囲まれたかのように扱われます。 文字ケースは保持されます。

  • 変数置換とサブ式展開 (§2.3.5.2) は 、expandable-string-literals および expandable-here-string-literals 内で行われます。

  • 引用符内のテキストを使用すると、引数の値に先頭、末尾、埋め込みの空白を含められます。 [: 引用符で囲まれた引数に空白が存在しても、1 つの引数が複数の引数に変換されることはありません。 メモの終了]

  • 引数の周囲にかっこを付けた場合、元の式のテキストではなく、結果が渡された状態で式が評価されます。

  • switch パラメーター (§2.3.4) のように見えるが、そのように意図されていない引数を渡すには、その引数を引用符で囲みます。

  • [switch]型制約 (§8.10.5) を持つパラメーターと一致する引数を指定すると、引数名がそれ自体に存在すると、そのパラメーターが$trueに設定されます。 ただし、引数にサフィックスを追加することで、パラメーターの値を明示的に設定できます。 たとえば、型制約パラメーター p を指定すると、 -p:$true の引数は p を True に、 -p:$false は p を False に設定します。

  • --の引数は、それに続くすべての引数が、その周りに二重引用符が配置されたかのように実際の形式で渡されることを示します。

  • --%の引数は、それに続くすべての引数が、最小限の解析と処理で渡されることを示します。 この引数は verbatim パラメーターと呼ばれます。 逐語的パラメーターの後の引数は、構文的に有効な PowerShell 式であっても、PowerShell 式ではありません。

コマンドの種類が Application の場合、パラメーター --% はコマンドに渡されません。 --%後の引数には、環境変数 (%で囲まれた文字列) が展開されています。 例えば次が挙げられます。

echoargs.exe --% "%path%" # %path% is replaced with the value $Env:path

引数の評価順序は指定されていません。

パラメーター バインドの詳細については、 §8.14 を参照してください。 名前参照の詳細については、 §3.8 を参照してください。

引数の処理が完了すると、コマンドが呼び出されます。 呼び出されたコマンドが正常に終了した場合 (§8.5.4)、コントロールは、コマンド呼び出しの直後にスクリプトまたは関数内のポイントに戻ります。 異常終了の動作の詳細については、 break (§8.5.1)、 continue (§8.5.2)、 throw (§8.5.3)、 exit (§8.5.5)、 try (§8.7)、および trap (§8.8) を参照してください。

通常、コマンドは、その名前と引数を使用して呼び出されます。 ただし、コマンド呼び出し演算子 > を使用できます。 コマンド名にエスケープされていない空白が含まれている場合は、引用符で囲んで、この演算子を使用して呼び出す必要があります。 スクリプト ブロックには名前がないため、この演算子を使用して呼び出す必要もあります。 たとえば、コマンド呼び出し Get-Factorial の次の呼び出しは同等です。

Get-Factorial 5
& Get-Factorial 5
& "Get-Factorial" 5

直接および間接的な再帰関数呼び出しが許可されます。 たとえば、

function Get-Power([int]$x, [int]$y) {
    if ($y -gt 0) { return $x * (Get-Power $x (--$y)) }
    else { return 1 }
}

例:

New-Object 'int[,]' 3,2
New-Object -ArgumentList 3,2 -TypeName 'int[,]'

dir E:\PowerShell\Scripts\*statement*.ps1 | ForEach-Object {$_.Length}

dir E:\PowerShell\Scripts\*.ps1 |
    Select-String -List "catch" |
    Format-Table Path, LineNumber -AutoSize

8.3 if ステートメント

構文:

if-statement:
    if new-lines~opt~ ( new-lines~opt~ pipeline new-lines~opt~ ) statement-block
        elseif-clauses~opt~ else-clause~opt~

elseif-clauses:
    elseif-clause
    elseif-clauses elseif-clause

elseif-clause:
    new-lines~opt~ elseif new-lines~opt~ ( new-lines~opt~ pipeline new-lines~opt~ ) statement-block

else-clause:
    new-lines~opt~ else statement-block

説明:

式を制御する パイプライン は、型 bool を持っているか、その型に暗黙的に変換できる必要があります。 else 句は省略可能です。 0 個以上の elseif 句が存在する可能性があります。

最上位レベルの パイプライン が True をテストすると、その ステートメント ブロック が実行され、ステートメントの実行が終了します。 それ以外の場合、 elseif 句 が存在する場合、 パイプライン で True がテストされた場合、その ステートメント ブロック が実行され、ステートメントの実行が終了します。 それ以外の場合、 else 句 が存在する場合は、 そのステートメント ブロック が実行されます。

例:

$grade = 92
if ($grade -ge 90) { "Grade A" }
elseif ($grade -ge 80) { "Grade B" }
elseif ($grade -ge 70) { "Grade C" }
elseif ($grade -ge 60) { "Grade D" }
else { "Grade F" }

8.4 Iteration ステートメント

8.4.1 while ステートメント

構文:

while-statement:
    while new-lines~opt~ ( new-lines~opt~ while-condition new-lines~opt~ ) statement-block

while-condition:
    new-lines~opt~ pipeline

説明:

制御式 while-condition は、型 bool を持っているか、その型に暗黙的に変換できる必要があります。 ステートメント ブロックで構成されるループ本体は、制御式が False をテストするまで繰り返し実行されます。 制御式は、ループ本体の各実行前に評価されます。

例:

$i = 1
while ($i -le 5) {                     # loop 5 times
    "{0,1}`t{1,2}" -f $i, ($i*$i)
    ++$i
}

8.4.2 do ステートメント

構文:

do-statement:
    do statement-block new-lines~opt~ while new-lines~opt~ ( while-condition new-lines~opt~ )
    do statement-block new-lines~opt~ until new-lines~opt~ ( while-condition new-lines~opt~ )

while-condition:
    new-lines~opt~ pipeline

説明:

制御式 while-condition は、型 bool を持っているか、その型に暗黙的に変換できる必要があります。 while 形式では、 ステートメント ブロックで構成されるループ本体が繰り返し実行され、制御式は True をテストします。 until フォームでは、制御式が True をテストするまでループ本体が繰り返し実行されます。 制御式は、ループ本体の各実行後に評価されます。

例:

$i = 1
do {
    "{0,1}`t{1,2}" -f $i, ($i * $i)
}
while (++$i -le 5)                 # loop 5 times

$i = 1
do {
    "{0,1}`t{1,2}" -f $i, ($i * $i)
}
until (++$i -gt 5)                 # loop 5 times

8.4.3 for ステートメント

構文:

for-statement:
    for new-lines~opt~ (
        new-lines~opt~ for-initializer~opt~ statement-terminator
        new-lines~opt~ for-condition~opt~ statement-terminator
        new-lines~opt~ for-iterator~opt~
        new-lines~opt~ ) statement-block

    for new-lines~opt~ (
        new-lines~opt~ for-initializer~opt~ statement-terminator
        new-lines~opt~ for-condition~opt~
        new-lines~opt~ ) statement-block

    for new-lines~opt~ (
        new-lines~opt~ for-initializer~opt~
        new-lines~opt~ ) statement-block

for-initializer:
    pipeline

for-condition:
    pipeline

for-iterator:
    pipeline

説明:

条件の制御式は、型 bool を持っているか、その型に暗黙的に変換できる必要があります。 ステートメント ブロックで構成されるループ本体は、制御式が True をテストしている間に繰り返し実行されます。 制御式は、ループ本体の各実行前に評価されます。

初期化子の式は、制御式の最初の評価の前に評価されます。 初期化子の式は、その副作用についてのみ評価されます。生成されるすべての値は破棄され、パイプラインに書き込まれません。

反復子の式は、ループ本体の各実行後に評価されます。 反復子の式は、その副作用についてのみ評価されます。生成されるすべての値は破棄され、パイプラインに書き込まれません。

条件の式を省略すると、制御式は True をテストします。

例:

for ($i = 5; $i -ge 1; --$i) { # loop 5 times
    "{0,1}`t{1,2}" -f $i, ($i * $i)
}

$i = 5
for (; $i -ge 1; ) { # equivalent behavior
    "{0,1}`t{1,2}" -f $i, ($i * $i)
    --$i
}

8.4.4 foreach ステートメント

構文:

foreach-statement:
    foreach new-lines~opt~ foreach-parameter~opt~ new-lines~opt~
        ( new-lines~opt~ variable new-lines~opt~ *in* new-lines~opt~ pipeline
        new-lines~opt~ ) statement-block

foreach-parameter:
    -parallel

説明:

ステートメント ブロックで構成されるループ本体は、パイプラインによって指定されたコレクション内の変数変数によって指定された各要素に対して実行されます。 変数のスコープは、foreach ステートメントに限定されません。 そのため、ループ本体の実行が完了した後も、最終的な値が保持されます。 パイプラインがコレクションではなくスカラー (値$nullを除く) を指定した場合、そのスカラーは 1 つの要素のコレクションとして扱われます。 パイプライン$null値を指定した場合、パイプラインは 0 個の要素のコレクションとして扱われます。

foreach-parameter-parallel が指定されている場合、動作は実装定義です。

foreach-parameter‑parallel はワークフローでのみ使用できます (§8.10.2)。

すべての foreach ステートメントには、独自の列挙子 (§2.3.2.2§4.5.16) が$foreachされており、そのループの実行中にのみ存在します。

パイプラインによって生成されたオブジェクトは、ステートメント ブロックの実行が開始される前に収集されます。 ただし、 ForEach-Object コマンドレットを使用すると、生成される各オブジェクトに対して ステートメント ブロック が実行されます。

例:

$a = 10, 53, 16, -43
foreach ($e in $a) {
    ...
}
$e # the int value -43

foreach ($e in -5..5) {
    ...
}

foreach ($t in [byte], [int], [long]) {
    $t::MaxValue # get static property
}

foreach ($f in Get-ChildItem *.txt) {
    ...
}

$h1 = @{ FirstName = "James"; LastName = "Anderson"; IDNum = 123 }
foreach ($e in $h1.Keys) {
    "Key is " + $e + ", Value is " + $h1[$e]
}

8.5 フロー制御ステートメント

構文:

flow-control-statement:
    break label-expression~opt~
    continue label-expression~opt~
    throw pipeline~opt~
    return pipeline~opt~
    exit pipeline~opt~

label-expression:
    simple-name
    unary-expression

説明:

フロー制御ステートメントを使用すると、制御が他の場所に無条件に転送されます。

8.5.1 break ステートメント

説明:

ラベル式を持つ break ステートメントは、ラベル付き break ステートメントと呼ばれます。 ラベル式のない break ステートメントは、ラベル付けされていない break ステートメントと呼ばれます。

トラップ ステートメントの外部では、ラベル付けされていない break ステートメントがイテレーション ステートメント (§8.4) 内で直接、その最小外側の反復ステートメントの実行を終了します。 ラベルのない break ステートメントは、switch ステートメント (§8.6) 内で直接、現在のスイッチの switch 条件のパターン マッチングを終了します。 トラップ ステートメント内からの break の使用の詳細については、(§8.8) を参照してください。

反復ステートメントまたは switch ステートメントは、必要に応じて、1 つのステートメント ラベル (§8.1.1) の直前に置く場合があります。このようなステートメント ラベルは、ラベル付き break ステートメントのターゲットとして使用できます。その場合、そのステートメントは、対象の外側の反復ステートメントの実行を終了します。

ラベル付きの区切りをローカル スコープで解決する必要はありません。一致するラベルを検索すると、スクリプトと関数呼び出しの境界を越えて呼び出し履歴が続行される可能性があります。 一致するラベルが見つからない場合、現在のコマンド呼び出しは終了します。

label-expression で指定されたラベルの名前に定数値を指定する必要はありません。

label-expression単項式の場合は、文字列に変換されます。

例:

$i = 1
while ($true) { # infinite loop
    if ($i * $i -gt 100) {
        break # break out of current while loop
    }
    ++$i
}

$lab = "go_here"
:go_here
for ($i = 1; ; ++$i) {
    if ($i * $i -gt 50) {
        break $lab # use a string value as target
    }
}

:labelA
for ($i = 1; $i -le 2; $i++) {

    :labelB
    for ($j = 1; $j -le 2; $j++) {

        :labelC
        for ($k = 1; $k -le 3; $k++) {
            if (...) { break labelA }
        }
    }
}

8.5.2 continue ステートメント

説明:

ラベル式を持つcontinue ステートメントは、ラベル付き continue ステートメントと呼ばれます。 ラベル式のない continue ステートメントは、ラベルのない continue ステートメントと呼ばれます。

トラップ ステートメント内からの continue の使用については、 §8.8 で説明します。

ループ内のラベルのない continue ステートメントは、現在のループの実行を終了し、最も小さい外側の反復ステートメント (§8.4) の右中かっこに制御を転送します。 スイッチ内のラベルのない continue ステートメントは、現在の switch イテレーションの実行を終了し、制御を最も小さい外側の switchswitch-condition (§8.6) に転送します

反復ステートメントまたは switch ステートメント (§8.6) は、必要に応じて、1 つのステートメント ラベル (§8.1.1) の直前に置く場合があります。 このようなステートメント ラベルは、囲まれたラベル付きの continue ステートメントのターゲットとして使用できます。その場合、そのステートメントは現在のループまたは switch イテレーションの実行を終了し、対象の外側の反復処理または switch ステートメント ラベルに制御を転送します。

ラベル付き continue は、どのローカル スコープでも解決する必要はありません。一致するラベルを検索すると、スクリプトと関数呼び出しの境界を越えて呼び出し履歴が continue される可能性があります。 一致するラベルが見つからない場合、現在のコマンド呼び出しは終了します。

label-expression で指定されたラベルの名前に定数値を指定する必要はありません。

label-expression単項式の場合は、文字列に変換されます。

例:

$i = 1
while (...) {
    ...
    if (...) {
        continue # start next iteration of current loop
    }
    ...
}

$lab = "go_here"
:go_here
for (...; ...; ...) {
    if (...) {
        continue $lab # start next iteration of labeled loop
    }
}

:labelA
for ($i = 1; $i -le 2; $i++) {

    :labelB
    for ($j = 1; $j -le 2; $j++) {

        :labelC
        for ($k = 1; $k -le 3; $k++) {
            if (...) { continue labelB }
        }
    }
}

8.5.3 throw ステートメント

説明:

例外は、システム レベルまたはアプリケーション レベルのエラー条件を処理する方法です。 throw ステートメントによって例外が発生します。 (例外処理の説明については、 §8.7 を参照してください。

パイプラインが省略され、throw ステートメントが catch 句にない場合、動作は実装定義されます。 パイプラインが存在し、throw ステートメントが catch 句内にある場合、その catch 句によってキャッチされた例外は、catch 句に関連付けられている finally 句が実行された後に再スローされます。

パイプラインが存在する場合、スローされる例外の型は実装定義です。

例外がスローされると、例外を処理できる外側の try ステートメントの最初の catch 句に制御が転送されます。 例外が最初にスローされる場所は、 スロー ポイントと呼ばれます。 例外がスローされると、 §8.7 で説明されている手順は、例外に一致する catch 句が見つかるか、見つからないまで繰り返し実行されます。

例:

throw
throw 100
throw "No such record in file"

パイプラインが省略され、throw ステートメントが catch 句内にない場合、"ScriptHalted" というテキストがパイプラインに書き込まれ、発生した例外の型がSystem.Management.Automation.RuntimeException

パイプラインが存在する場合、発生した例外はSystem.Management.Automation.RuntimeException型のオブジェクトにラップされます。これには、例外に関する情報がSystem.Management.Automation.ErrorRecord オブジェクト ($_ 経由でアクセス可能) が含まれます。

例 1: throw 123RuntimeException 型の例外が発生します。 catch ブロック内から、 $_.TargetObject には、内部にラップされたオブジェクトが含まれています。この場合、値が 123 の System.Int32

例 2: throw "xxx"RuntimeException 型の例外が発生します。 catch ブロック内から、 $_.TargetObject には、内部にラップされたオブジェクトが含まれています。この場合、値が "xxx" の System.String

例 3: throw 10,20 すると 、RuntimeException 型の例外が発生します。 catch ブロック内から、$_.TargetObjectには、Systemを持つ 2 つの要素の制約のない配列であるSystem.Object[]内にラップされたオブジェクトが含まれます。Int32' 値 10 および 20。

8.5.4 return ステートメント

説明:

return ステートメントは、パイプラインによって指定された値 (存在する場合) をパイプラインに書き込み、関数またはスクリプトの呼び出し元に制御を返します。 1 つの関数またはスクリプトに、0 個以上の return ステートメントを含めることがあります。

実行が関数の右中かっこに達した場合、パイプラインのない暗黙的なreturnが想定されます。

returnステートメントは、プログラマが他の言語で可能な限り自分自身を表現できるようにするための「構文糖」です。ただし、関数またはスクリプトから返される値は、実際には、その関数またはスクリプトによってパイプラインに書き込まれたすべての値に加えて、パイプラインで指定された任意の値です。 スカラー値のみがパイプラインに書き込まれる場合、その型は返される値の型です。それ以外の場合、戻り値の型は、パイプラインに書き込まれるすべての値を含む制約のない 1 次元配列です。

例:

function Get-Factorial ($v) {
    if ($v -eq 1) {
        return 1 # return is not optional
    }

    return $v * (Get-Factorial ($v - 1)) # return is optional
}

Get-Factorialする呼び出し元は、intを取得します。

function Test {
    "text1" # "text1" is written to the pipeline
    # ...
    "text2" # "text2" is written to the pipeline
    # ...
    return 123 # 123 is written to the pipeline
}

Testする呼び出し元は、3 つの要素の制約のない 1 次元配列を取得します。

8.5.5 exit ステートメント

説明:

exit ステートメントは、現在のスクリプトを終了し、制御と 終了コード をホスト環境または呼び出し元スクリプトに返します。 パイプラインが指定されている場合、指定した値は必要に応じて int に変換されます。 このような変換が存在しない場合、または パイプライン を省略した場合は、int 値 0 が返されます。

例:

exit $count # terminate the script with some accumulated count

8.6 switch ステートメント

構文:

switch-statement:
    switch new-lines~opt~ switch-parameters~opt~ switch-condition switch-body

switch-parameters:
    switch-parameter
    switch-parameters switch-parameter

switch-parameter:
    -Regex
    -Wildcard
    -Exact
    -CaseSensitive
    -Parallel

switch-condition:
    ( new-lines~opt~ pipeline new-lines~opt~ )
    -File new-lines~opt~ switch-filename

switch-filename:
    command-argument
    primary-expression

switch-body:
    new-lines~opt~ { new-lines~opt~ switch-clauses }

switch-clauses:
    switch-clause
    switch-clauses switch-clause

switch-clause:
    switch-clause-condition statement-block statement-terimators~opt~

switch-clause-condition:
    command-argument
    primary-expression

説明:

switch-condition が 1 つの値を指定する場合、1 つ以上の一致するパターン ステートメント ブロックに制御が渡されます。 一致するパターンがない場合は、既定のアクションを実行できます。

スイッチには、それぞれパターン (既定以外の switch 句) またはキーワード default (既定の switch 句) で始まる 1 つ以上の switch 句が含まれている必要があります。 スイッチには、0 個または 1 個の default スイッチ句と、0 個以上の既定以外の switch 句が含まれている必要があります。 Switch 句は任意の順序で記述できます。

複数のパターンが同じ値を持つ場合があります。 パターンはリテラルである必要はありません。スイッチには異なる型のパターンが含まれる場合があります。

switch-condition の値がパターン値と一致する場合は、そのパターンのステートメント ブロックが実行されます。 複数のパターン値が switch-condition の値と一致する場合、それらのステートメント ブロックのいずれかが break ステートメント (§8.5.1) を含む場合を除き、一致する各パターンのステートメント ブロックが字句順で実行されます。

switch-condition の値がパターン値と一致しない場合、default switch 句が存在する場合は、そのステートメント ブロックが実行されます。それ以外の場合は、そのスイッチ条件のパターン マッチングが終了します。

スイッチは入れ子にすることができ、各スイッチには独自の switch 句のセットがあります。 このような場合、switch 句は現在スコープ内の最も内側のスイッチに属します。

ステートメント ブロックに入ると、$_には、制御がそのステートメント ブロックに移動する原因となった switch 条件の値が自動的に割り当てられます。 $_ は、その ステートメント ブロックswitch-clause-condition でも使用できます。

文字列以外の照合は、等しいかどうかをテストすることによって行われます (§7.8.1)。

一致に文字列が含まれる場合、既定では、比較では大文字と小文字が区別されません。 switch-parameter が存在すると-CaseSensitive比較では大文字と小文字が区別されます。

パターンにはワイルドカード文字 (§3.15) が含まれている場合があります。この場合、ワイルドカード文字列の比較が実行されますが、 switch-parameter-Wildcard が存在する場合にのみ実行されます。 既定では、比較では大文字と小文字が区別されません。

パターンには正規表現 (§3.16) を含め、その場合は正規表現文字列の比較が実行されますが、 switch-parameter-Regex が存在する場合にのみ実行されます。 既定では、比較では大文字と小文字が区別されません。 -Regexが存在し、パターンが一致する場合、$Matchesはそのパターンの switch-clauseステートメント ブロックで定義されます。

switch-parameter は省略可能です。パラメーターの個別の先頭部分を使用できます。 たとえば、 ‑Regex‑Rege‑Reg‑Re‑R は同等です。

競合する switch-parameters を指定すると、構文的に最後のパラメーターが優先されます。 ‑Exactが存在すると、-Regex-Wildcardが無効になります。ただし、‑Caseには影響しません。

switch-parameter‑Parallel が指定されている場合、動作は実装定義です。

switch-parameter‑Parallel は、ワークフロー (§8.10.2) でのみ使用できます。

パターンが script-block 式の場合、そのブロックが評価され、必要に応じて結果が bool に変換されます。 結果の値が $true場合、対応する ステートメント ブロック が実行されます。それ以外の場合は実行されません。

switch-condition が複数の値を指定する場合、スイッチは、単一の値を指定するスイッチ条件に対して上記の規則を使用して字句順に各値に適用されます。 すべての switch ステートメントには、 $switch 独自の列挙子 (§2.3.2.2§4.5.16) があり、そのスイッチの実行中にのみ存在します。

switch ステートメントにはラベルがあり、ラベル付きおよびラベルなし改行 (§8.5.1) および続行 (§8.5.2) ステートメントを含む場合があります。

switch-condition-Fileswitch-filename の場合、式内の値を反復処理するのではなく、switch-filename で指定されたファイル内の値を反復処理します。ファイルは、値を構成する各行で一度に 1 行ずつ読み取られます。 行ターミネータ文字は値に含まれません。

例:

$s = "ABC def`nghi`tjkl`fmno @#$"
$charCount = 0; $pageCount = 0; $lineCount = 0; $otherCount = 0
for ($i = 0; $i -lt $s.Length; ++$i) {
    ++$charCount
    switch ($s[$i]) {
        "`n" { ++$lineCount }
        "`f" { ++$pageCount }
        "`t" { }
        " " { }
        default { ++$otherCount }
    }
}

switch -Wildcard ("abc") {
    a* { "a*, $_" }
    ?B? { "?B? , $_" }
    default { "default, $_" }
}

switch -Regex -CaseSensitive ("abc") {
    ^a* { "a*" }
    ^A* { "A*" }
}

switch (0, 1, 19, 20, 21) {
    { $_ -lt 20 } { "-lt 20" }
    { $_ -band 1 } { "Odd" }
    { $_ -eq 19 } { "-eq 19" }
    default { "default" }
}

8.7 try/finally ステートメント

構文:

try-statement:
    try statement-block catch-clauses
    try statement-block finally-clause
    try statement-block catch-clauses finally-clause

catch-clauses:
    catch-clause
    catch-clauses catch-clause

catch-clause:
    new-lines~opt~ catch catch-type-list~opt~
    statement-block

catch-type-list:
    new-lines~opt~ type-literal
    catch-type-list new-lines~opt~ , new-lines~opt~

type-literalfinally-clause:
    new-lines~opt~ finally statement-block

説明:

try ステートメントは、ブロックの実行中に発生する例外をキャッチするためのメカニズムを提供します。 また、try ステートメントは、コントロールが try ステートメントを離れたときに常に実行されるコード ブロックを指定する機能も提供します。 throw ステートメントを使用して例外を発生させるプロセスについては、 §8.5.3 で説明されています。

try ブロックは、try ステートメントに関連付けられたステートメント ブロックです。 catch ブロックは、catch 句に関連付けられたステートメント ブロックです。 finally ブロックは、finally 句に関連付けられたステートメント ブロックです。

catch-type-list のない catch 句は、一般的な catch 句と呼ばれます。

catch 句例外ハンドラーであり、 catch-type-list に 発生した例外の型が含まれる catch句は一致する catch 句です。 一般的な catch 句は、すべての例外の種類と一致します。

catch 句finally 句は省略可能ですが、少なくとも 1 つが存在する必要があります。

スローされた例外の処理は、例外に一致する catch 句が見つかるまで、次の手順を繰り返し評価することで構成されます。

  • 現在のスコープでは、スロー ポイントを囲む各 try ステートメントが調べられます。 最も内側の try ステートメントから始まり、最も外側の try ステートメントで終わる各 try ステートメント について、次の手順が評価されます。

    • Stry ブロックがスロー ポイントを囲み、S に 1 つ以上の catch 句がある場合、catch 句は構文的に調べられ、例外に適したハンドラーが見けられます。 例外の種類または例外の種類の基本型を指定する最初の catch 句は、一致と見なされます。 一般的な catch 句は、すべての例外の種類に一致すると見なされます。 一致する catch 句がある場合、例外処理は、その catch 句のブロックに制御を転送することによって完了します。 一致する catch 句内で、変数 $_ には現在の例外の説明が含まれています。

    • それ以外の場合、tryブロックまたはScatchブロックがスローポイントを囲み、Sfinallyブロックがある場合は、finallyブロックに制御が転送されます。 finally ブロックによって別の例外がスローされた場合、現在の例外の処理は終了されます。 それ以外の場合、制御が finally ブロックの末尾に達すると、現在の例外の処理が続行されます。

  • 例外ハンドラーが現在のスコープに存在しない場合、外側のスコープに対して上記の手順が繰り返され、現在のスコープが呼び出されたステートメントに対応するスロー ポイントが返されます。

  • 例外処理によってすべてのスコープが終了し、例外のハンドラーが存在しないことを示す場合、動作は指定されません。

try ブロック内で到達できない catch 句を防ぐために、catch 句は、その同じ try ブロック内の以前の catch 句で指定された型と等しいか、その型から派生した例外型を指定しない場合があります。

finally ブロックのステートメントは、制御が try ステートメントを離れるときに常に実行されます。 これは、通常の実行の結果、 breakcontinue、または return ステートメントの実行の結果として制御転送が発生した場合、または try ステートメントから例外がスローされた結果として発生する場合に当てはまります。

finally ブロックの実行中に例外がスローされた場合は、次に囲むtryステートメントに例外がスローされます。 別の例外が処理中であった場合、その例外は失われます。 例外を生成するプロセスについては、 throw ステートメントの説明で詳しく説明します。

try ステートメントは、 trap ステートメントと共存できます。詳細については 、§8.8 を参照してください。

例:

$a = New-Object 'int[]' 10
$i = 20 # out-of-bounds subscript

while ($true) {
    try {
        $a[$i] = 10
        "Assignment completed without error"
        break
    }

    catch [IndexOutOfRangeException] {
        "Handling out-of-bounds index, >$_<`n"
        $i = 5
    }

    catch {
        "Caught unexpected exception"
    }

    finally {
        # ...
    }
}

スローされた各例外は、 System.Management.Automation.RuntimeExceptionとして発生します。 try ブロックに型固有の catch 句がある場合、例外の InnerException プロパティが検査され、上記の型System.IndexOutOfRangeExceptionなど、一致するものが検索されます。

8.8 トラップステートメント

構文:

trap-statement:
    *trap* new-lines~opt~ type-literal~opt~ new-lines~opt~ statement-block

説明:

型リテラルを含むtrapステートメントと指定しないステートメントは、catch ブロック (§8.7) にそれぞれ catch-type-list を指定した場合と使用しない場合に似ていますが、trap ステートメントで一度にトラップできる型は 1 つだけです。

複数の trap ステートメントを同じ ステートメント ブロックで定義でき、定義の順序は関係ありません。 同じ型リテラルを持つ 2 つのtrap ステートメントが同じスコープで定義されている場合、構文的に最初のステートメントを使用して、一致する型の例外が処理されます。

catch ブロックとは異なり、trap ステートメントは例外の型と完全に一致します。派生型の一致は実行されません。

例外が発生した場合、現在のスコープに一致する trap ステートメントが存在しない場合は、外側のスコープで一致するトラップ ステートメントが検索されます。これには、呼び出し元のスクリプト、関数、フィルター、その呼び出し元などを検索する必要があります。 検索によってすべてのスコープが終了し、例外のハンドラーが存在しないことを示す場合、動作は指定されません。

trapステートメントのステートメント本文は、対応する例外を処理するためにのみ実行されます。それ以外の場合は、実行が渡されます。

trapステートメント本文が正常に終了した場合、既定ではエラー オブジェクトがエラー ストリームに書き込まれ、例外が処理されたと見なされ、例外を表示したtrap ステートメントを含むスコープ内のステートメントの直後にステートメントが続きます。 例外の原因は、 trap ステートメントを含むコマンドによって呼び出されたコマンドにある可能性があります。

trapステートメント本体で実行された最後のステートメントが続行される場合 (§8.5.2)、エラー ストリームへのエラー オブジェクトの書き込みは抑制され、例外を表示したトラップ ステートメントを含むスコープ内のステートメントの直後にステートメントが続きます。 trapステートメント本体で実行された最後のステートメントが break (§8.5.1) の場合、エラー ストリームへのエラー オブジェクトの書き込みは抑制され、例外が再スローされます。

trapステートメント内の変数$_には、現在のエラーの説明が含まれています。

try ブロック内から発生した例外に一致するcatch ブロックはありませんが、一致するtrap ステートメントが上位のブロック レベルで存在する場合について考えてみます。 try ブロックの finally 句が実行されると、親スコープに一致するcatch ブロックがある場合でも、trap ステートメントは制御を取得します。 trap ステートメントが try ブロック自体内で定義されていて、そのtry ブロックに一致するcatch ブロックがある場合、trap ステートメントは制御を取得します。

例:

次の例では、エラー オブジェクトが書き込まれ、トラップの原因となったステートメントの直後のステートメントで実行が続行されます。つまり、"完了" がパイプラインに書き込まれます。

$j = 0; $v = 10/$j; "Done"
trap { $j = 2 }

次の例では、エラー オブジェクトの書き込みは抑制され、トラップの原因となったステートメントの直後のステートメントで実行が続行されます。つまり、"完了" がパイプラインに書き込まれます。

$j = 0; $v = 10/$j; "Done"
trap { $j = 2; continue }

次の例では、エラー オブジェクトの書き込みが抑制され、例外が再スローされます。

$j = 0; $v = 10/$j; "Done"
trap { $j = 2; break }

次の例では、トラップステートメントと例外生成ステートメントは同じスコープ内にあります。 例外がキャッチされて処理されると、パイプラインに 1 を書き込んで実行が再開されます。

&{trap{}; throw '\...'; 1}

次の例では、トラップステートメントと例外生成ステートメントは異なるスコープにあります。 例外がキャッチされて処理されると、パイプラインに (1 ではなく) 2 を書き込んで実行が再開されます。

trap{} &{throw '\...'; 1}; 2

8.9 データステートメント

構文:

data-statement:
    data new-lines~opt~ data-name data-commands-allowed~opt~ statement-block

data-name:
    simple-name

data-commands-allowed:
    new-lines~opt~ -SupportedCommand data-commands-list

data-commands-list:
    new-lines~opt~ data-command
    data-commands-list , new-lines~opt~ data-command

data-command:
    command-name-expr

説明:

データ ステートメントは 、データ セクションを作成し、そのセクションのデータをコードから分離します。 この分離は、エラー メッセージやヘルプ文字列など、テキスト用の個別の文字列リソース ファイルなどの機能をサポートします。 また、異なる言語に翻訳される文字列の分離、検索、および処理を容易にすることで、国際化をサポートするのにも役立ちます。

スクリプトまたは関数には、0 個以上のデータ セクションを含めることができます。

データ セクションの ステートメント ブロック には、次の PowerShell 機能のみが含まれます。

  • を除くすべての演算子 -match
  • if ステートメント
  • 次の自動変数: $PSCulture$PSUICulture$true$false、および $null
  • コメント
  • Pipelines
  • セミコロン (;) で区切られたステートメント
  • リテラル
  • ConvertFrom-StringData コマンドレットの呼び出し
  • SupportedCommand パラメーターを使用して識別されるその他のコマンドレット

ConvertFrom-StringData コマンドレットを使用する場合は、任意の形式の文字列リテラルを使用してキーと値のペアを表すことができます。 ただし、 expandable-string-literals と expandable-here-string-literals には、変数の置換やサブ式の拡張を含めてはなりません。

例:

SupportedCommand パラメーターは、指定されたコマンドレットまたは関数がデータのみを生成することを示します。 たとえば、次のデータ セクションには、XML ファイル内のデータを書式設定するユーザー作成コマンドレット ConvertTo-Xmlが含まれています。

data -SupportedCommand ConvertTo-Xml {
    Format-Xml -Strings string1, string2, string3
}

次の例では、データ セクションに文字列をハッシュ テーブルに変換する ConvertFrom-StringData コマンドが含まれており、その値は $messages に割り当てられます。

$messages = data {
    ConvertFrom-StringData -StringData @'
    Greeting = Hello
    Yes = yes
    No = no
'@
}

ハッシュ テーブルのキーと値には、それぞれ $messages.Greeting$messages.Yes、および $messages.Noを使用してアクセスします。

これで、これは英語リソースとして保存できます。 次のデータ セクションを使用して、ドイツ語とスペイン語のリソースを別々のファイルに作成できます。

$messages = data {
    ConvertFrom-StringData -StringData @"
    Greeting = Guten Tag
    Yes = ja
    No = nein
"@
}

$messagesS = data {
    ConvertFrom-StringData -StringData @"
    Greeting = Buenos días
    Yes = sí
    No = no
"@
}

dataname が存在する場合は、データ ステートメントの値を格納する変数に名前を付けます (先頭の$を使用しません)。 具体的には、 $name = data { ... }data name { ... }と同等です。

8.10 関数の定義

構文:

function-statement:
    function new-lines~opt~ function-name function-parameter-declaration~opt~ { script-block }
    filter new-lines~opt~ function-name function-parameter-declaration~opt~ { script-block }
    workflow new-lines~opt~ function-name function-parameter-declaration~opt~ { script-block }

function-name:
    command-argument

command-argument:
    command-name-expr

function-parameter-declaration:
    new-lines~opt~ ( parameter-list new-lines~opt~ )

parameter-list:
    script-parameter
    parameter-list new-lines~opt~ , script-parameter

script-parameter:
    new-lines~opt~ attribute-list~opt~ new-lines~opt~ variable script-parameter-default~opt~

script-block:
    param-block~opt~ statement-terminators~opt~ script-block-body~opt~

param-block:
    new-lines~opt~ attribute-list~opt~ new-lines~opt~ param new-lines~opt~
        ( parameter-list~opt~ new-lines~opt~ )

parameter-list:
    script-parameter
    parameter-list new-lines~opt~ , script-parameter

script-parameter-default:
    new-lines~opt~ = new-lines~opt~ expression

script-block-body:
    named-block-list
    statement-list

named-block-list:
    named-block
    named-block-list named-block

named-block:
    block-name statement-block statement-terminators~opt~

block-name: one of
    dynamicparam   begin   process   end

説明:

関数定義では、定義する関数、フィルター、またはワークフローの名前と、パラメーターの名前 (存在する場合) を指定します。 また、その関数の目的を達成するために実行される 0 個以上のステートメントも含まれています。

各関数は、クラス System.Management.Automation.FunctionInfoのインスタンスです。

8.10.1 フィルター関数

通常の関数はパイプラインで 1 回実行され、 $inputを介して入力コレクションにアクセスしますが、 フィルター は、入力コレクション内のオブジェクトごとに 1 回実行される特殊な種類の関数です。 現在処理中のオブジェクトは、変数 $_を介して使用できます。

名前付きブロックを持たないフィルター (§8.10.7) は、プロセス ブロックがある関数と同等ですが、開始ブロックまたは終了ブロックはありません。

次のフィルター関数の定義と呼び出しについて考えてみましょう。

filter Get-Square2 { # make the function a filter
    $_ * $_ # access current object from the collection
}

-3..3 | Get-Square2 # collection has 7 elements
6, 10, -3 | Get-Square2 # collection has 3 elements

各フィルターは、クラス System.Management.Automation.FilterInfo のインスタンスです (§4.5.11)。

8.10.2 ワークフロー関数

ワークフロー関数は、実装で定義されたセマンティクスを持つ通常の関数に似ています。 ワークフロー関数は、一連の Windows Workflow Foundation アクティビティに変換され、Windows Workflow Foundation エンジンで実行されます。

8.10.3 引数処理

Get-Powerと呼ばれる関数については、次の定義を検討してください。

function Get-Power ([long]$Base, [int]$Exponent) {
    $result = 1
    for ($i = 1; $i -le $Exponent; ++$i) {
        $result *= $Base
    }
    return $result
}

この関数には、 $Base$Exponentの 2 つのパラメーターがあります。 また、負でない指数値の場合は、 $Base^$Exponent^ を計算し、結果を Get-Powerの呼び出し元に返すステートメントのセットも含まれています。

スクリプト、関数、またはフィルターの実行が開始されると、各パラメーターは対応する引数の値に初期化されます。 対応する引数がなく、既定値 (§8.10.4) が指定されている場合は、その値が使用されます。それ以外の場合は、 $null 値が使用されます。 そのため、各パラメーターは、 script-block の開始時に代入によって初期化された場合と同様に、新しい変数です。

スクリプト パラメーターに型制約 (上記の[long][int]など) が含まれている場合、対応する引数の値は必要に応じてその型に変換されます。それ以外の場合、変換は行われません。

スクリプト、関数、またはフィルターの実行が開始されると、変数 $args は制約のない 1 次元配列として定義されます。これには、名前または位置にバインドされていないすべての引数が構文上の順序で含まれます。

次の関数の定義と呼び出しについて考えてみましょう。

function F ($a, $b, $c, $d) { ... }

F -b 3 -d 5 2 4       # $a is 2, $b is 3, $c is 4, $d is 5, $args Length 0
F -a 2 -d 3 4 5       # $a is 2, $b is 4, $c is 5, $d is 3, $args Length 0
F 2 3 4 5 -c 7 -a 1   # $a is 1, $b is 2, $c is 7, $d is 3, $args Length 2

パラメーター バインドの詳細については、 §8.14 を参照してください。

8.10.4 パラメーター初期化子

パラメーター p の宣言には初期化子が含まれている場合があります。この場合、p が呼び出しの引数にバインドされていない場合、その初期化子の値を使用して p を初期化します。

次の関数の定義と呼び出しについて考えてみましょう。

function Find-Str ([string]$Str, [int]$StartPos = 0) { ... }

Find-Str "abcabc" # 2nd argument omitted, 0 used for $StartPos
Find-Str "abcabc" 2 # 2nd argument present, so it is used for $StartPos

8.10.5 [switch] 型制約

switch パラメーターを渡す場合は、コマンド内の対応するパラメーターを型スイッチによって制約する必要があります。 型スイッチには、True と False の 2 つの値があります。

次の関数の定義と呼び出しについて考えてみましょう。

function Process ([switch]$Trace, $P1, $P2) { ... }

Process 10 20                # $Trace is False, $P1 is 10, $P2 is 20
Process 10 -Trace 20         # $Trace is True, $P1 is 10, $P2 is 20
Process 10 20 -Trace         # $Trace is True, $P1 is 10, $P2 is 20
Process 10 20 -Trace:$false  # $Trace is False, $P1 is 10, $P2 is 20
Process 10 20 -Trace:$true   # $Trace is True, $P1 is 10, $P2 is 20

8.10.6 パイプラインと関数

パイプラインでスクリプト、関数、またはフィルターを使用すると、値のコレクションがそのスクリプトまたは関数に配信されます。 スクリプト、関数、またはフィルターは、列挙子$input (§2.3.2.2§4.5.16) を介してそのコレクションにアクセスします。これは、そのスクリプト、関数、またはフィルターへのエントリで定義されます。

次の関数の定義と呼び出しについて考えてみましょう。

function Get-Square1 {
    foreach ($i in $input) {   # iterate over the collection
        $i * $i
    }
}

-3..3 | Get-Square1            # collection has 7 elements
6, 10, -3 | Get-Square1        # collection has 3 elements

8.10.7 名前付きブロック

スクリプト ブロック内のステートメントは、1 つの大きな名前のないブロックに属することも、1 つ以上の名前付きブロックに分散することもできます。 名前付きブロックを使用すると、パイプラインからのコレクションをカスタム処理できます。名前付きブロックは任意の順序で定義できます。

begin ブロック内のステートメント (つまり、キーワード begin でマークされたステートメント) は、最初のパイプライン オブジェクトが配信される前に 1 回実行されます。

プロセス ブロック内のステートメント (つまり、キーワード プロセスでマークされたステートメント) は、配信されるパイプライン オブジェクトごとに実行されます。 ($_ は、パイプラインからの入力コレクションから処理されている現在のオブジェクトへのアクセスを提供します)。つまり、0 個の要素のコレクションがパイプラインを介して送信された場合、プロセス ブロックはまったく実行されません。 ただし、スクリプトまたは関数がパイプライン コンテキストの外部で呼び出された場合、このブロックは 1 回だけ実行され、 $_ は現在のコレクション オブジェクトがないため、 $nullに設定されます。

終了ブロック内のステートメント (つまり、キーワード end でマークされたステートメント) は、最後のパイプライン オブジェクトが配信された後に 1 回実行されます。

8.10.8 dynamicparam ブロック

これまでの §8.10 のサブセクションでは、ソース コードの一部として定義されている 静的パラメーターが扱われます。 キーワード dynamicparamでマークされている別の形式の名前付きブロック (§8.10.7) を使用して、動的パラメーターを定義することもできます。 この機械の多くは実装が定義されています。

動的パラメーターは、特定の条件下でのみ使用できるコマンドレット、関数、フィルター、またはスクリプトのパラメーターです。 そのようなケースの 1 つは、Set-Item コマンドレットの Encoding パラメーターです。

ステートメント ブロックでは、if ステートメントを使用して、関数でパラメーターを使用できる条件を指定します。 New-Object コマンドレットを使用して、パラメーターを表す実装定義型のオブジェクトを作成し、その名前を指定します。 また、 New-Object を使用して、別の実装定義型のオブジェクトを作成し、パラメーターの実装定義属性を表します。

次の例は、Name と Path という標準パラメーターを持つ関数と、 DP1 という名前のオプションの動的パラメーターを示しています。 DP1 パラメーターは PSet1 パラメーター セット内にあり、Int32の種類があります。 DP1 パラメーターは、Path パラメーターの値に "HKLM:" が含まれている場合にのみ、HKEY_LOCAL_MACHINE レジストリ ドライブで使用されていることを示します。

function Sample {
    param ([string]$Name, [string]$Path)
    dynamicparam {
        if ($Path -match "*HKLM*:") {
            $dynParam1 = New-Object System.Management.Automation.RuntimeDefinedParameter("dp1", [int32], $attributeCollection)

            $attributes = New-Object System.Management.Automation.ParameterAttribute
            $attributes.ParameterSetName = 'pset1'
            $attributes.Mandatory = $false

            $attributeCollection = New-Object -Type System.Collections.ObjectModel.Collection``1[System.Attribute]
            $attributeCollection.Add($attributes)

            $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
            $paramDictionary.Add("dp1", $dynParam1)
            return $paramDictionary
        }
    }
}

動的パラメーターを表すオブジェクトの作成に使用される型は System.Management.Automation.RuntimeDefinedParameter

パラメーターの属性を表すオブジェクトの作成に使用される型は System.Management.Automation.ParameterAttribute

パラメーターの実装定義属性には、 MandatoryPositionValueFromPipeline が含まれます。

8.10.9 param ブロック

パラメーター ブロックは、パラメーターを宣言する別の方法を提供します。 たとえば、次のパラメーター宣言のセットは同等です。

function FindStr1 ([string]$Str, [int]$StartPos = 0) { ... }
function FindStr2 {
    param ([string]$Str, [int]$StartPos = 0) ...
}

param ブロックでは param ブロック属性リストが許可されますがfunction-parameter-declaration では許可されません。

スクリプトには param ブロック を含め、 関数パラメーター宣言を含めないようにすることができます。 関数またはフィルター定義には 、function-parameter-declaration または param-block を含め、両方を含めないようにすることができます。

次の例を確認してください。

param ( [Parameter(Mandatory = $true, ValueFromPipeline=$true)]
        [string[]] $ComputerName )

1 つのパラメーター ( $ComputerName) には型 string[]があり、必須であり、パイプラインから入力を受け取ります。

Parameter 属性とその他の例については、§12.3.7 を参照してください。

8.11 並列ステートメント

構文:

parallel-statement:
    *parallel* statement-block

並列ステートメントには、実装で定義された方法で実行される 0 個以上のステートメントが含まれています。

並列ステートメントは、ワークフロー (§8.10.2) でのみ使用できます。

8.12 sequence ステートメント

構文:

sequence-statement:
    *sequence* statement-block

シーケンス ステートメントには、実装で定義された方法で実行される 0 個以上のステートメントが含まれています。

シーケンス ステートメントは、ワークフロー (§8.10.2) でのみ使用できます。

8.13 inlinescript ステートメント

構文:

inlinescript-statement:
    inlinescript statement-block

inlinescript ステートメントには、実装で定義された方法で実行される 0 個以上のステートメントが含まれています。

インラインスクリプト ステートメントは、ワークフロー (§8.10.2) でのみ使用できます。

8.14 パラメーターバインド

スクリプト、関数、フィルター、またはコマンドレットが呼び出されると、各引数を位置によって対応するパラメーターにバインドでき、最初のパラメーターの位置は 0 になります。

Get-Powerと呼ばれる関数の次の定義フラグメントとその呼び出しについて考えてみましょう。

function Get-Power ([long]$Base, [int]$Exponent) { ... }

Get-Power 5 3       # argument 5 is bound to parameter $Base in position 0
                    # argument 3 is bound to parameter $Exponent in position 1
                    # no conversion is needed, and the result is 5 to the power 3

Get-Power 4.7 3.2   # double argument 4.7 is rounded to int 5, double argument
                    # 3.2 is rounded to int 3, and result is 5 to the power 3

Get-Power 5         # $Exponent has value $null, which is converted to int 0

Get-Power           # both parameters have value $null, which is converted to int 0

スクリプト、関数、フィルター、またはコマンドレットが呼び出されると、引数を名前で対応するパラメーターにバインドできます。 これを行うには、 引数と共にパラメーターを使用します。引数は、先頭にダッシュ (-) が付いたパラメーターの名前で、その引数に関連付けられた値が続きます。 使用されるパラメーター名は、大文字と小文字を区別しない任意のスペルを持ち、対応するパラメーターを一意に指定する任意のプレフィックスを使用できます。 パラメーター名を選択するときは、 共通パラメーターの名前を使用しないでください。

関数 Get-Powerに対する次の呼び出しについて考えてみましょう。

Get-Power -Base 5 -Exponent 3   # -Base designates $Base, so 5 is
                                # bound to that, -Exponent designates
                                # $Exponent, so 3 is bound to that

Get-Power -Exp 3 -Bas 5         # $Base takes on 5 and $Exponent takes on 3

Get-Power -E 3 -B 5             # $Base takes on 5 and $Exponent takes on 3

一方、次の関数を呼び出します。

function Get-Hypot ([double]$Side1, [double]$Side2) {
    return [Math]::Sqrt($Side1 * $Side1 + $Side2 * $Side2)
}

パラメーターを一意に指定するプレフィックスがないため、パラメーター -Side1-Side2を使用する必要があります。

同じパラメーター名を、異なる関連する引数値の有無にかかわらず複数回使用することはできません。

パラメーターには属性を含めることができます (§12)。 個々の属性の詳細については、 §12.3 内のセクションを参照してください。 パラメーター セットの詳細については、 §12.3.7 を参照してください。

スクリプト、関数、フィルター、またはコマンドレットは、呼び出しコマンド ライン、パイプライン、またはその両方から引数を受け取ることができます。 パラメーター バインドを解決するための手順を次に示します。

  1. すべての名前付きパラメーターをバインドし、次に
  2. 位置パラメーターをバインドし、次に
  3. 正確に一致する値 (§12.3.7) でパイプラインからバインドします。
  4. 変換を使用して値 (§12.3.7) でパイプラインからバインドします。
  5. 正確に一致する名前 (§12.3.7) でパイプラインからバインドします。
  6. 変換を使用して名前 (§12.3.7) でパイプラインからバインドする

これらの手順の一部には、§6 で説明されているように変換が含 まれます。 ただし、バインドで使用される変換のセットは、言語変換で使用される変換とまったく同じではありません。 具体的には

  • $null ブール値にキャストできますが、 $nullboolにバインドすることはできません。
  • $null値がコマンドレットの switch パラメーターに渡されると、$trueが渡されたかのように扱われます。 ただし、関数の switch パラメーターに渡されると、 $false が渡されたかのように扱われます。
  • ブール型またはスイッチ型のパラメーターは、数値またはブール値の引数にのみバインドできます。
  • パラメーター型がコレクションではなく、引数が何らかのコレクションである場合、パラメーター型が object または PsObject でない限り、変換は試行されません。 (この制限の主なポイントは、コレクションを文字列パラメーターに変換できないようにすることです)。それ以外の場合は、通常の変換が試行されます。

パラメーターの型が IList または ICollection<T>の場合は、コンストラクター、op_Implicit、およびop_Explicitを使用した変換のみが試行されます。 このような変換が存在しない場合は、 IListICollection<T>、配列を含む 、"collection" 型のパラメーターに対する特別な変換が使用されます。

位置指定パラメーターは、可能であれば、型変換なしでバインドすることを好みます。 たとえば、

function Test {
    [CmdletBinding(DefaultParameterSetName = "SetB")]
    param([Parameter(Position = 0, ParameterSetName = "SetA")]
        [decimal]$Dec,
        [Parameter(Position = 0, ParameterSetName = "SetB")]
        [int]$In
    )
    $PSCmdlet.ParameterSetName
}

Test 42d   # outputs "SetA"
Test 42    # outputs "SetB"