したがって、通常、私はテキスト処理(特に大容量ファイルの場合)を見つける傾向がsed
あり、通常はシェル自体でこれらの操作を実行しないでください。
しかし、私はこれが変わることができると思います。私はあちこちを見てman ksh
よりこれを見つけました。
<#pattern Seeks forward to the beginning of the
next line containing pattern.
<##pattern The same as <# except that the por‐
tion of the file that is skipped is
copied to standard output.
実際の実用性に懐疑的で、一度試してみることにしました。私はそうしました:
seq -s'foo bar
' 1000000 >file
...次のような100万行のデータについて:
1foo bar
...
999999foo bar
1000000
...そして、sed
以下と比較してみてください。
p='^[^0-8]99999.*bar'
for c in "sed '/$p/q'" "ksh -c ':<##@(~(E)$p)'"
do </tmp/file eval "time ( $c )"
done | wc -l
したがって、両方のコマンドを達成する必要があります。999999プワこれを行うには、パターンマッチング実装で少なくとも各行の開始と終了を評価する必要があります。また、負のパターンに対して最初の文字を検証する必要があります。簡単なことですが...結果は私が期待していたものとは異なります。
( sed '/^[^0-8]99999.*bar/q' ) \
0.40s user 0.01s system 99% cpu 0.419 total
( ksh -c ':<##@(~(E)^[^0-8]99999.*bar)' ) \
0.02s user 0.01s system 91% cpu 0.033 total
1999997
ksh
ここでは ERE とsed
BRE が使用されます。以前はシェルモードで同じことをしましたが、ksh
結果は変わりませんでした。
ksh
それにもかかわらず、これは10倍を超える非常に重要な違いですsed
。以前、David Kornが自分のio libを作成し、それを実装したことを読んだことがありますksh
。関連がありますか? - しかし、私はそれについてほとんど何も知りません。シェルはなぜそんなにうまく機能しますか?
私にとってもっと驚くべきことは、ksh
ユーザーが要求した場所にオフセットを残すことです。得るために(ほぼ)また(牛のような栄養の一種) sed
あなたは使用する必要があります-u
-非常に遅い。
以下はgrep
v。ksh
テストです。
1000000 #grep + head
( grep -qm1 '^[^0-8]99999.*bar'; head -n1; ) \
0.02s user 0.00s system 90% cpu 0.026 total
999999foo bar #ksh + head
( ksh -c ':<#@(~(E)^[^0-8]99999.*bar)'; head -n1; ) \
0.02s user 0.00s system 73% cpu 0.023 total
ksh
ここでは、ビットはgrep
、必ずしもそうではありませんが、ほぼ密接に接続されています。しかし、まだ素晴らしいです。そして ksh
head
プレビューを開始するための入力を提供今後一致します。
事実というにはとても良いようだと思いました。これらのコマンドは、後で何が違うのですか?
ああ、そしてここにはサブシェルもないようです。
ksh -c 'printf %.5s "${<file;}"'
ベストアンサー1
kshは以下を使用するだけでなく、SFIOただし、独自のカスタムメモリアロケータを使用します。
それでも私の考えでは、sfioがこの場合に違いを生むということです。私はstraceで例を実行してみましたが、kshが約200回(65KBブロック)の読み取り/書き込みを呼び出し、sedが約3400回(4KBブロック)の読み取り/書き込みを呼び出すことがわかります。 sed -uを使用すると、私のラップトップはほとんど溶け、読み込みはバイト単位で、書き込みは行単位で行われます。 Kshは単にlseekを使用します。 Grepは約400個の読み取り(32KBブロック)を使用します。