Daher tendiere ich im Allgemeinen dazu, nach sedTextverarbeitung zu suchen - insbesondere nach großen Dateien - und vermeide es normalerweise, solche Dinge in der Shell selbst zu tun.
Ich denke jedoch, dass sich das ändern kann. Ich stöberte herum man kshund bemerkte Folgendes:
<#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.
Ich war skeptisch gegenüber der Nützlichkeit der realen Welt und beschloss, es auszuprobieren. Ich tat:
seq -s'foo bar
' 1000000 >file
... für eine Million Datenzeilen, die aussehen wie:
1foo bar
...
999999foo bar
1000000
... und stellte es gegen sedwie:
p='^[^0-8]99999.*bar'
for c in "sed '/$p/q'" "ksh -c ':<##@(~(E)$p)'"
do </tmp/file eval "time ( $c )"
done | wc -l
Daher sollten beide Befehle bis zu 999999foo bar erhalten, und ihre Implementierung für den Mustervergleich muss mindestens den Anfang und das Ende jeder Zeile auswerten, um dies zu tun. Sie müssen auch das erste Zeichen anhand eines negierten Musters überprüfen. Dies ist eine einfache Sache, aber ... Die Ergebnisse waren nicht das, was ich erwartet hatte:
( 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
kshverwendet hier ERE und sedein BRE. Ich habe das gleiche mit kshund einem Shell-Muster gemacht, aber die Ergebnisse unterschieden sich nicht.
Wie auch immer, das ist eine ziemlich bedeutende Diskrepanz - kshübertrifft das sedZehnfache. Ich habe vorher gelesen, dass David Korn seine eigene io lib geschrieben und implementiert hat ksh- möglicherweise hängt das damit zusammen? - aber ich weiß so gut wie nichts darüber. Wie kommt es, dass die Shell das so gut macht?
Noch erstaunlicher für mich ist, dass kshder Versatz wirklich genau dort bleibt, wo Sie ihn fragen. Um (fast) dasselbe aus (GNU) herauszuholen sed, muss man verwenden -u- sehr langsam .
Hier ist ein grepv. kshTest:
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
kshBeats grephier - aber nicht immer - sie sind ziemlich gebunden. Trotzdem ist das ziemlich gut und ksh bietet Lookahead - headdie Eingabe beginnt vor dem Match.
Es scheint einfach zu schön, um wahr zu sein, denke ich. Was machen diese Befehle unter der Haube anders?
Oh, und anscheinend gibt es hier nicht einmal eine Unterschale:
ksh -c 'printf %.5s "${<file;}"'
patternein regulärer Ausdruck oder ein einfacheres Shell-Muster?