sedを使用して連続ストリーミング出力を操作する方法は?


13

私は技術に詳しくない聴衆のためにプレゼンテーションをまとめています。値の連続ストリームを出力するbashで実行しているプログラムがありますが、そのうちのいくつかは重要です。重要な結果が表示されるときに強調表示して、聴衆がその頻度を把握できるようにします。問題はsed、実行中のストリームを操作できないことです。次のように結果をファイルに入れるとうまくいきます:

cat output.txt | sed "s/some text/some text bolded/"

しかし、次のように実行中の出力で同じことをしようとすると:

command | sed "s/some text/some text bolded/"

sed何もしません。何かご意見は?

ランバートは指摘するのに十分役に立ちましたので、私の言ったことsedは何も曖昧ではありませんでした。何が起こっstdoutているのかstderrは、たとえそれがパイプスルーされたとしても、プログラムが通常どおりに出力することです(書き込みを行っていないことはかなり確信しています)sed

問題は、コマンドが2番目のプログラムを呼び出し、それが標準出力に出力されることであるようです。最初のプログラムで印刷された数行があります。これらは編集できます。次に、2番目のプログラムによって出力される値のストリームがあります。これらは編集できません。

Perlおよびawkメソッドも機能しません。


5
DOESのstdbuf -o0 command | sed "s/some text/some text bolded/"作品?
FloHimself

3
「sedは何もしません」とは、置換が行われないことを意味しますか、または出力がありませんか?コマンドはstdoutの代わりにstderrに書き込みますか?使用する可能性のあるものを強調したい場合command|egrep 'some text|$'
ランバート

コマンドはstdoutに書き込みますか(stderrに書き込みませんか)?
アントン

1
テキストを追加する必要がありますより多くのあなた回表示されていることを考えるg:置換されるラインで、そうでない場合のみ最初の発生を得た「グローバルな」置換をsed "s/old/new/g"
ph0t0nix

@ ph0t0nixいいえ、それは問題ではありませんが、今後の問題でした。ヒントをありがとう。
Pジョーンズ

回答:


12

コマンドの出力がバッファリングされる可能性があります。コマンドが端末に書き込むと、バッファはすべての改行でフラッシュされるため、予想される速度で表示されます。コマンドがパイプに書き込むとき、バッファは数キロバイトに達したときにのみフラッシュされるため、大幅に遅れます。したがって、標準入出力ライブラリのデフォルトの動作です。

コマンドが出力をバフェットしないようにするには、unbuffer(expectから)またはstdbuf(GNU coreutilsから)を使用できます。

unbuffer command | sed …
stdbuf -o0 command | sed …

stdbuf動作しませんでした(先ほども述べましたが、ところで)unbuffer。あなたが私をどれほど幸せにしたかはわかりません。
P・ジョーンズ

そして、簡潔な説明をありがとう。非常に役立ちます。
P・ジョーンズ

sedここでの例が動作しない場合がありますので、それ自体があるため(ChennyStarポストCF)は、そのようなバッファを使用することsedcommandバッファー解除へ:cat /etc/passwd | unbuffer sedしかし、sed自身が持っている-uオプションをので、grepこの例では、よりsuiteableかもしれません。あなたの背景情報に感謝します!素晴らしい答えです!
数学

4

sed そのためのオプションがあります:

-u、-unbuffered

入力ファイルから最小限のデータをロードし、出力バッファをより頻繁にフラッシュします。詳細man sedを参照してください。


1
GNU sedのみ(BSD sedではありません)、これでもパイプの開始時のコマンドのバッファリングを妨げないと思います。しかし、それを言及するのは良いことです。:)
ワイルドカード

stdbufのマンページには、「COMMANDが標準ストリームのバッファリングを調整する場合(たとえば、 'tee'が調整する場合)、 'stdbuf'による対応する変更がオーバーライドされます。sedはこのカテゴリに該当するように見えますが、「-u」フラグを使用すると、バッファーなしのパイプチェーンで役立ちます。
-MattSmith

2

私はawkを使用します

  command | awk '/some important stuff/ { printf "%c[31m%s%c[0m\n",27,$0,27 ; next }
  { print ; } '

どこ

  • /some important stuff/ sedのように重要な行を選択します
  • printf "%c[31m%s%c[0m\n",27,$0,27 ; 赤で印刷
    • 緑、黄色に32,33を使用します...
    • $ 1、$ 2を使用して特定のフィールドを選択できます
  • 他の行は「そのまま」印刷されます

重要な点は、command行をフラッシュすることですが、大量の出力がある場合はそうする必要があります。


注:質問では、行全体を「太字」にする必要はなく、「テキスト」だけにする必要があります。awksub()またはを使用gsub())でその機能を実装することもできますが、このプリミティブ置換の場合sedは確かに適切なツールです。
ジャニス

1

perlの方法:

command | perl -pe 's/(stuff)/\x1b[1m$1\x1b[0m/g'

または連続出力:

出力用のbashスクリプトcont

#!/bin/bash
while [ true ]
do
   echo "Some stuff"
done

でテストする:

./cont | perl -pe 's/(stuff)/\x1b[1m${1}\x1b[0m/g'
  • \x1b[1m -太字または強度の増加
  • ${1} -後方参照
  • \x1b[0m -すべての属性をリセット

出力:

あるもの
あるもの
あるもの
あるもの

その他のエスケープコードはこちら

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.