sedが文字列を見つけたときに尾を止める方法は? [コピー]

sedが文字列を見つけたときに尾を止める方法は? [コピー]

tailすべての行が別のファイルに書き込まれるまで一致するものを見つけたら、コマンドを終了したいと思います。

tail -f logfile | sed '/special string/q'  | tee output.txt

Output.txtには、特殊文字列が見つかるまで行が含まれます。しかし、問題はその後tailコマンドを終了したいということです。

ベストアンサー1

明示的に殺す必要があります。

seq 1 10 > file
tail -f file | { sed /7/q; pkill -PIPE -xg0 tail; } | tee output

pkill -PIPE -xg0 tail方法

私たちと同じプロセスグループに属するSIGPIPEプロセスにシグナルを送信します。tail

tailこれは、同じプロセスグループで別のプロセスが実行されていないと仮定します。コマンドが対話型端末(ジョブ制御を含むシェル)で実行される場合、各パイプは独自のプロセスグループ(ジョブとも呼ばれます)で実行されるため、安全でなければなりません。ジョブ制御のないシェル(スクリプトなど)では、ジョブ制御が明示的にオンになっている別のシェルにパイプをラップできます。

sh -mc 'tail -f file | { sed /7/q; pkill -PIPE -xg0 tail; }' | tee output

しかし、GNUテールは自分で死ぬでしょう。

bashとcoreutilsでLinuxボックスを使用すると、すべてが正常で何も必要なく、自動的にシャットダウンkillされtailます。

debian$ tail -f file | sed /2/q
1
2
debian$ # WOW!

tailこれは、GNU coreutilsが標準出力がまだ有効であることを確認するために賢いトリックを使用するためです。書き込み可能:「準備」のポーリング中です。読む「エラーが発生した場合、パイプのもう一方の端が閉じているかのように、パイプの書き込み端でのみ発生する条件です。この場合、信号でtail簡単に自殺できますSIGPIPE。 」ソースコード:

  FD_SET (STDOUT_FILENO, &rfd);

  /* readable event on STDOUT is equivalent to POLLERR,
     and implies an error condition on output like broken pipe.  */
  if (select (STDOUT_FILENO + 1, &rfd, NULL, NULL, &delay) == 1)
    die_pipe ();

[実際には他のシステムでこれを実行または置き換えるPOLLHUPことができますが、実際には重要ではありません。]POLLHUP|POLLINPOLLERR

GNUテールは、ソケットやttyではなくパイプでのみこれを行います。つまり、Knee Unixドメインソケットを使用して「パイプ」を実装するksh93では機能しません。

また、私が知っている限り、GNUだけがtailこれを行い、バージョンでのみ可能です。8.28; Linuxでもbusyboxtailにはありません。

これは、使用tail -f | quit_at_some_point(ここにある多くの答えで判断)が依然として非常に付随的であり、実際には終わらない可能性があることを意味します。

おすすめ記事