我正在尝试一次有效地匹配多个模式,这在原则上非常有效:
echo abcdef | awk \
'/abc/ {print "match abc"}
/def/ {print "match def"}'
此外,我想匹配记录中的所有事件:
echo abcabc | awk \
'function findall(str, re) {
while(match(str, re)) {
print "match", re;
str = substr(str, RSTART+RLENGTH)
}
}
{
findall($0, "abc");
}'
现在扩展上面的示例以匹配多个模式我最终会得到一系列findall调用:
findall($0, "abc");
...
findall($0, "def");
问题在于,使用许多不同的模式(> 100),这种方法的表现几乎不如第一个样本。这是有道理的,因为我想这个模式不会出现在同一个自动机中。
有没有办法加快一点速度?例如提供具有多种模式的“匹配”。我想我可以连接模式(abc | def),但是我会松开那些模式完全匹配的信息。
更新:应匹配每一次:
abcabc
123
abcxyz
因为输入数据会产生 2个匹配记录(给定标准分隔符)但 4匹配整个数据如果与模式“abc”和“xyz”一起使用。 这篇文章中的第一个样本至少报告 3个匹配,但未能检测到第一个记录中多次出现的“abc”
答案 0 :(得分:2)
以这种方式做到这一点:
您将模式放在一个文件中,每个模式都放在一行中,而不是放在awk函数中。
e.g。
kent$ cat p.txt
abc
def
foo
xxx
然后你可以加载文件,让awk为你做匹配的工作。最后,只打印出与输入字符串匹配的模式:
echo inputString|awk 'NR==FNR{ps[$0]=0;next;}
{for(p in ps)if(match($0,p))ps[p]++;}
END{for(p in ps) if(ps[p]>0)print p" matched"}' p.txt -
当然,您可以替换" - "如果需要,请输入文件。
小测试:
kent$ echo "abcdefoobarblah"|awk 'NR==FNR{ps[$0]=0;next;}{for(p in ps)if(match($0,p))ps[p]++;}END{for(p in ps) if(ps[p]>0)print p" matched"}' p.txt -
def matched
foo matched
abc matched
所以,模式" xxx"没有匹配。只打印出def,foo,abc。
注意脚本可以优化并缩短。例如,保存END {}块,在第一个for循环中执行打印。然而,它告诉你我的想法如何处理它。
编辑OP的评论
乔,我没有看到你问题中匹配时间的要求。但要实现并不困难。请参阅下面的测试,并附上示例文本:kent$ echo "abcabcabcdefoobarblah"|
awk 'NR==FNR{ps[$0]=0;next;}
{for(p in ps){t=$0;ps[p]=gsub(p,"",t);}}
END{for(p in ps) if(ps[p]>0)print p" matched "ps[p]" time(s)"}' p.txt -
<强>输出:强>
def matched 1 time(s)
foo matched 1 time(s)
abc matched 3 time(s)