今更の感じはするが、Foreach-Objectの動作。
PS>1..3 | ForEach-Object{"開始"}{"ループ"}{"終了"} |
本来、ヘルプを見ると位置オペランドは(-Process)だけなので、なぜこれで動くのだろうとちょっと疑問に思う。
ちなみに、以下は良いが、
PS>1..3 | ForEach-Object{"開始"}{"ループ"} |
当然、以下は上と同じ書式なので「ループ」が初期処理とみなされる。
PS>1..3 | ForEach-Object{"ループ"}{"終了"} |
なので、
PS>1..3 | ForEach-Object{"ループ"} -end{"終了"} |
とする必要が有りそう。
ForEach-Object{"開始"}{"ループ"}{"終了"}
返信削除としたときは、まず一つ目の値である{"開始"}が、位置パラメータである-Processパラメータにバインドされます。
残りの{"ループ"}と{"終了"}は-RemainingScriptsパラメータにバインドされます。
-RemainingScriptsパラメータが何故そういう挙動をするかというと、
このパラメータはScriptBlock[]を受けられ、ValueFromRemainingArguments = Trueという属性が付いているため、
バインドされなかった残りのパラメータ値をすべてまとめて配列化してこのパラメータにバインドされるためです。
結局のところ、実行されているのは以下のコマンドになります。
ForEach-Object -Process {"開始"} -RemainingScripts {"ループ"},{"終了"}
つまりはRemainingScriptsにスクリプトブロックがバインドされたときは、-ProcessパラメータでBeginの処理が走ることになって何とも奇妙なのですが、これは構文上の利便性を重視したことによる弊害(?)なんでしょうね。
ちなみに、-ProcessもScriptBlock[]を受けられるので、
ForEach-Object {"開始"},{"ループ"},{"終了"}
という書き方もできます。
あと個人的にはForEach-Object{"ループ"} -end{"終了"}ではなく、
ForEach-Object {} {"ループ"} {"終了"}
とするかな…。
いつもコメントありがとうございます。
返信削除非常にためになりました。
ヘルプを見ると、RemainingScriptsパラメータは3.0から追記されていますので、BeginやEndが指定されない限り2.0では基本的にProcessが全部引き受けているのですかね・・・。(もしくはヘルプの漏れか・・・)
>ForEach-Object {} {"ループ"} {"終了"}
これについては私も実践ではそうすると思います。
実は今、社内向けの簡単な解説テキストを作っていて、教科書的にはForEach-Object{"ループ"} -end{"終了"}かなぁと思ったりしていました。
また、よろしくお願いいたします。