Тож, загалом, я схильний шукати 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
Таким чином, обидві команди повинні мати до 999999фотосмуга, і їх реалізація відповідності шаблону повинна оцінювати принаймні початок і кінець кожного рядка, щоб це зробити. Вони також повинні перевірити перший знак за запереченим малюнком. Це проста справа, але ... Результати не були такими, які я очікував:
( 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 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
регулярний вираз чи простіший шаблон оболонки?