Итак, в общем, я склонен обращать внимание на 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
... для миллиона строк данных, которые выглядят так:
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 bar, и их реализация сопоставления с образцом должна оценивать как минимум начало и конец каждой строки, чтобы сделать это. Они также должны проверить первый символ по отрицательному шаблону. Это простая вещь, но ... Результаты оказались не такими, как я ожидал:
( 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 здесь и sedBRE. Я делал то же самое с kshшаблоном оболочки, но результаты не отличались.
Во всяком случае, это довольно существенное расхождение - kshпревосходит в sed10 раз. Я читал ранее, что Дэвид Корн написал свою собственную библиотеку IO и реализует ее в ksh- возможно, это связано? - но я почти ничего не знаю об этом. Как это оболочка делает это так хорошо?
Еще более удивительным для меня является то, что он kshдействительно оставляет свое смещение там, где вы его просите. Чтобы получить (почти) то же самое из (GNU), sed вы должны использовать -u- очень медленно .
Вот тест grepv.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регулярное выражение или более простой шаблон оболочки?