web-dev-qa-db-ja.com

出力を書き込んだ直後にsedが終了しないのはなぜですか?

大きなファイルでsedを実行し、 pv ユーティリティを使用して、入力の読み取りと出力の書き込みの速度を確認しました。 pvは、sedが約5秒以内に入力を読み取り、出力を書き込んだことを示しましたが、sedはさらに20〜30秒間終了しませんでした。どうしてこれなの?

これが私が見た出力です:

pv -cN source input.txt | sed "24629045,24629162d" | pv -cN output > output.txt
   source: 2.34GB 0:00:06 [ 388MB/s] [==========================================================================================================>] 100%            
   output: 2.34GB 0:00:05 [ 401MB/s] [              <=>                                                                                                           ]
5
Brandon Liu

2つの理由があります。そもそも、quitには伝えません。

考えてみましょう:

_seq 10 | sed -ne1,5p
_

その場合、入力行の前半をprintするだけですが、残りの行をEOFまで読み取る必要があります。代わりに:

_seq 10|sed 5q
_

すぐに終了します。

また、各プロセスの間に遅延があります。したがって、pvが4kbでバッファリングし、sedが4kbをバッファリングする場合、最後のpvは入力より8kb遅れます。その数はそれよりも多い可能性が高いです。

GNU/BSD/AST sedを使用して_-u_スイッチを試すことができますが、それはほぼ間違いなくnotは役に立ちません大きな入力でのパフォーマンス。 GNU sed with _-u_を呼び出すと、入力のすべてのバイトに対してread()になります。他のオブジェクトについては調べていません。そのような状況で行いますが、私はそれらが異なることをすると信じる理由はありません.3つのドキュメントすべて_-u_はunbufferedを意味します-そしてそれはストリームが関係する、かなり一般的に理解されている概念。

あなたがするかもしれないもう一つのことは、sedriteコマンドと1つ以上で明示的にラインバッファwoutputですwrite-file [s]という名前。それでも少し遅くなりますが、おそらく他の方法よりも優れています。

これは、次のようなsedを使用して実行できます。

_sed -n 'w outfile'
_

sedwriteコマンドは常に即時です-バッファなしの出力です。また、(デフォルト)sedはラインサイクルごとに1回コマンドを適用するため、sedを簡単に使用して効果的に使用できますパイプラインの途中でもラインバッファI/O。そうすれば、少なくとも、次のように、2番目のpvsedでほぼ最新の状態に保つことができます。

_pv ... | sed -n '24629045,24629162!w /dev/fd/1' | pv ...
_

...それは_/dev/fd/[num]_リンクを提供するシステムを想定していますが(つまり、実質的にすべてのLinuxベースのシステム-Android -および 他にも多数上記のリンクの可用性に失敗した場合、同じことを行うには、mkfifoとを使用して独自のパイプを明示的に作成できます。これを最後のpvのstdinとして使用し、sedwriteファイルとして名前を付けます。

3
mikeserv