ように、想定した通りの結果が得られます。このように、上流のスクリプトブロックのendブロック内にforeachなどループブロックが存在し、そのループブロック内で下流に値を出力している場合はうまくいきます。(ちなみに、スクリプトブロック直下に記述するのとendブロック内に記述するのは等価。"とすると、コンソールに1と2が改行区切りで表示されますが、ホストに表示されるだけで$resultには値は格納されません。スクリプト化して実行した場合は、Write-Hostが実行されることすらなく、スクリプトが終了してしまいます。breakだとなぜうまくいかないのか結局どういうことかというと、パイプライン下流のbreakは、パイプラインを打ち切る処理をするのではなく、単に一つ上流のブロックをbreakする処理に過ぎないのです。endのいずれかのブロックがbreakされてしまい、結果としてスクリプトが終了してしまうわけですね。このSelect-WhileTest関数だと大丈夫ですが、processブロックの中にループブロックを記述し、その中でbreakを書くのは当然ダメです。そのループを抜けるだけなので、上流の出力は止まってくれません。breakではなくcontinueを使う場合も基本は同じ結果です。continueは所詮、その名の通り継続処理なので、上流に以下のような無限リストがあると無限ループに陥ってしまいます。System.Management.Automation.PipelineStoppedException)を実行する方法も見かけますが、これはループブロックがあっても強制的にスクリプトが終了するので余計ダメです。try...catchでエラートラップすればスクリプトの終了は回避できますが、「パイプラインが正常終了せずエラーを出した」扱いであることには代わりないので、やはり出力を変数に格納することができません。前述のbreakを使った方法の問題点のうち、上流にループブロックがないとスクリプトが終了してしまい、出力を変数に代入することもできない問題は、とりあえず解決する方法があります。以下のように、呼び出す時にパイプライン全体をダミーのループブロックでラップすれば良いのです。"このようにしておけば、breakはパイプラインの外側のdo...untilを抜ける効果になるので、スクリプトが終了する心配も、値を出力しない問題も起こりません。パイプライン上流にループブロックが存在する場合でも、単にdoループ内の処理が1回走るだけなので、特に問題は起きません。$i++){}とかでも良いです。...この記述を美しいと思う人は多分いないですね。事情を知らないと意味不明ですし。breakを記述する側の関数には、前述の通りのループブロック内では値を出力できないという制限は残ったままになります。breakでパイプラインを打ち切るのは、本来想定された動作かと言われるとかなり微妙なところだと思います。処理が変わったことについては、ご存知の方も多いかと思います。具体的には、v2までは単にパイプライン処理をすべて終了してから、最初のn件を抽出する処理であったn件のパイプライン出力がされた後は、入力をすべてフィルタし出力に流さなくなる動作であったところが、v3からはn件のパイプライン出力がされた時点で、パイプラインの処理を打ち切るようになりました。