そのため、一般的に、私は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
したがって、両方のコマンドは最大999999fooバーを取得する必要があり、それらのパターンマッチング実装は、少なくとも各行の最初と最後を評価する必要があります。また、否定パターンに対して最初の文字を検証する必要があります。これは簡単なことですが...結果は期待したものではありませんでした。
( 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
以前、シェルパターンで同じことを行いましたが、結果に違いはありませんでした。
とにかく、それはかなり重要な不一致です-10倍以上のksh
パフォーマンスを発揮sed
します。以前に、David Kornが彼自身のio libを書いてそれを実装することを読んだことがありますksh
-おそらくこれは関連していますか?-しかし、私はそれについてほとんど何も知りません。シェルはこれをどのようにうまく行うのですか?
私にとってさらに驚くべきことはksh
、あなたが尋ねるところに、そのオフセットを正しく残していることです。(GNU)から(ほぼ)同じものを取得するには、使用する必要があります- 非常に遅い。 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;}"'
pattern
正規表現または単純なシェルのパターン?