PowerShell で SIGPIPE 連鎖
元ネタは『Windows PowerShell (正式版リリース)1.0 (376-)』.
旧バージョン
(追記) 色々ご指摘をいただき,それを受けての改良版が下の方にあります.
#PowerShell 1.0 filter yes { while($true){ "y" } } filter take([int] $n) { if(0 -gt --$n) { break } $_ }
こうやって,
yes | take 10000 | take 1
これがちゃんと 1 行だけ出力して止まる.SIGPIPE 連鎖っぽい.すげえ.
下のは止まらないっぽい.
yes | select -First 10000 | select -First 1
追記
- PowerShellにおけるパイプの動作について - モジバケーション
- Take の実装について.参考になりました.ありがとうございます.
- Windows PowerShell (正式版リリース)1.0 (434-435) - Windows@2ch掲示板
- PowerShell 2.0 (CTP) で動作変わってるよという話
- break inside scriptblocks and in the pipeline - Karl Prosser - eggheadcafe.com
- 上の話と関連して
- http://www.techtalkz.com/microsoft-windows-powershell/164555-v1-break-inside-scriptblocks-pipeline.html:title=
- 上と同じ話.PowerShell の break や continue が,実は System.Management.Automation.FlowControlException 派生例外で実装されているというのは面白い.
- Steppable Pipelines in Powershell 2.0 CTP - Tao Ma - eggheadcafe.com
- 微妙に関係ありそうでなさそうな PowerShell 2.0 (CTP) の新機能.GetSteppablePipeline とか.
新バージョン
- take のバグフィックス
- 実験的に PowerShell v2.0 対策 (内部実装に依存する対策なので微妙)
- ストリーミング出力の自動フラット化を抑制 (LINQ のセマンティクスを採用)
- (追記)PowerShell v2.0 (CTP) で end block が実行されない問題対策
#PowerShell 2.0 filter yes { trap { continue } while($true){ "y" } } function take([int] $count) { begin { if(0 -ge $count) { break } } process { ,$_ if(0 -ge --$count) { break } } }
こうやって,
yes | take 10000 | take 1
内部的に break が例外というのはなるほどなんだけど,どこまでそれに依存していいかだなぁ.