Итак, в общем, я склонен обращать внимание на 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
регулярное выражение или более простой шаблон оболочки?Ответы:
Ksh не только использует sfio, но и использует собственный распределитель памяти.
Тем не менее, я думаю, что Sfio имеет значение в этом случае. Я только что попытался запустить ваш пример под strace и вижу, что ksh вызывает чтение / запись ~ 200 раз (блоки по 65 КБ), а sed делает это ~ 3400 раз (блоки по 4 КБ). С sed -u мой ноутбук почти растаял, чтение выполняется за байт, а запись - за строку. Кш просто использует lseek. Grep использует чтение ~ 400 раз (блоки 32 КБ).
источник
ksh
движок регулярных выражений в качестве io? В любом случае, большое спасибо за ответ. Мои извинения вашему ноутбуку. А как насчет пользовательского распределителя памяти? У вас есть еще что-нибудь об этом?