提取模式的最快方法

时间:2017-01-19 03:22:19

标签: linux awk sed grep

从输入中提取感兴趣子字符串的最快方法是什么?如下所示?

MsgTrace(65/26)noop:user=xxx=INBOX:cmd=534
ImapFetchComplete(56/39)user=xxxxxxxxxx

所需的输出(即本例中字符串:后面的MsgTrace(65/26) - 终止字符串):

noop

我尝试了以下内容,但没有成功:

egrep -i "[a-zA-Z]+\(.*\)[a-z]+:"

3 个答案:

答案 0 :(得分:2)

默认情况下,

grep会在给定输入行找到匹配项时返回整行

虽然选项-o仅将输出限制为正则表达式匹配的那一行,但在这种情况下仍然不够,因为您需要该匹配的子字符串

但是,由于您使用的是Linux,因此可以使用GNU grep的{​​{1}}选项(支持PCREs,Perl兼容的正则表达式) ,它允许通过-P(删除到目前为止匹配的所有内容)和\K等功能提取子匹配(一个不会对匹配做出贡献的前瞻断言) ):

(?=...)

可选背景信息:

Ed Morton指出(在已删除的评论中)GNU $ grep -Po "[a-zA-Z]\(.*\)\K[a-z]+(?=:)" <<'EOF' MsgTrace(65/26)noop:user=xxx=INBOX:cmd=534 ImapFetchComplete(56/39)user=xxxxxxxxxx EOF noop # output 的{​​{1}}页面仍然会调用grep选项&#34;高度实验&#34;可能&#34;警告未实现的功能&#34;,但该选项已存在多年,并且在实践中我还没有看到警告或性能问题 - YMMV。

在目前的情况下,上述命令甚至优于man-P解决方案 - 请参阅NeronLeVelu's helpful performance comparison

interesting article Ed指出 可以表面的潜在性能问题,例如sed(通过PCRE库),Perl本身使用的正则表达式引擎许多其他广泛使用的(和成熟的)正则表达式引擎,例如Python,Ruby和PHP:

  • 简而言之:这些引擎采用的递归回溯算法可能会导致严重的性能下降。将长表达式的长序列与可变长度量词串联起来的正则表达式,例如awk的{​​较长版本}以匹配grep -P
  • 文章认为,只有当正则表达式包含反向引用时才需要回溯,并且在不存在时应该使用不同的,更快的算法。

答案 1 :(得分:2)

你可以试试这个:

$ sed -n 's/[[:alpha:]]*([^)]*)\([[:lower:]]*\):.*/\1/p' file
noop

它可以移植到所有POSIX seds并且不使用PCRE,只使用BRE,因此regexp匹配部分至少应该很快。

答案 2 :(得分:2)

对这样一个样本条目的2469120行文本进行快速而肮脏的测试,将grep -PO作为获胜者

time sed -n -e 's/^MsgTrace[^)]\{4,\})//;t M' -e 'b' -e ':M' -e 's/:.*//p' YourFile >/dev/null
real    0m7.61s
user    0m7:10s
sys     0m0.13s

time awk -F ':' '/^MsgTrace/{ sub( /.*)/, "", $1); print $1}' YourFile >/dev/null
real    0m17.43s
user    0m16.19s
sys     0m0.17s

time grep -Po  "[a-zA-Z]\(.*\)\K[a-z]+(?=:)" YourFile >/dev/null
real    0m6.72s
user    0m6.23s
sys     0m0.11s

time sed -n 's/[[:alpha:]]*([^)]*)\([[:lower:]]*\):.*/\1/p' YourFile >/dev/null
real    0m17.43s
user    0m16.29s
sys     0m0.12s

time grep -Po '(?<=MsgTrace\(65/26\)).*?(?=:)' YourFile >/dev/null
real    0m16.38s
user    0m15.22s
sys     0m0.15s

对于@EdMorton问题(我重做相同的原始sed以在机器加载的相同上下文中具有比较值)。确切的字符串要快很多,我想sed在选择哪个是所有标准中最长的一个之前尝试几个组合,其中.*lpool is full提供更多的可能性

time sed -n -e 's/^MsgTrace([^)]\{3,\})//;T' -e 's/:.*//p' YourFile >/dev/null
real    0m7.28s
user    0m6.60s
sys     0m0.13s

time sed -n -e 's/^[[:alpha:]]*([^)]\{3,\})//;T' -e 's/:.*//p' YourFile >/dev/null
real    0m10.44s
user    0m9.67s
sys     0m0.14s

time sed -n -e 's/^[[:alpha:]]*([^)]*)//;T' -e 's/:.*//p' YourFile >/dev/null

real    0m10.54s
user    0m9.75s
sys     0m0.11s