因此,总的来说,我倾向于寻找sed
文本处理工具,尤其是大文件,并且通常避免在shell本身中做这些事情。
我认为,这可能会改变。我在四处闲逛,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
之前使用shell模式做过同样的事情,但是结果没有不同。
无论如何,这是一个相当大的差异- ksh
胜过sed
10倍。我之前读过David Korn编写了自己的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
的输入在匹配之前开始。
我想这似乎太不可思议了。这些命令在后台有何不同之处?
哦,显然这里没有子shell:
ksh -c 'printf %.5s "${<file;}"'
pattern
正则表达式还是更简单的shell模式?