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

追記

新バージョン

  • 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 が例外というのはなるほどなんだけど,どこまでそれに依存していいかだなぁ.