Итак, в общем, я склонен обращать внимание на 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 здесь и sed
BRE. Я делал то же самое с ksh
шаблоном оболочки, но результаты не отличались.
Во всяком случае, это довольно существенное расхождение - ksh
превосходит в sed
10 раз. Я читал ранее, что Дэвид Корн написал свою собственную библиотеку IO и реализует ее в 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
регулярное выражение или более простой шаблон оболочки?