grep两次或使用正则表达式一次更有效吗?

时间:2011-05-18 05:53:12

标签: bash unix grep

我正在尝试解析几个2gb +文件,并希望在几个级别上进行grep。

我想要获取包含“foo”的行和包含“bar”的行。

我可以grep foo file.log | grep bar,但我担心的是运行它会花费两倍。

使用像grep -E '(foo.*bar|bar.*foo)'这样的东西会有用吗?

4 个答案:

答案 0 :(得分:2)

grep -E '(foo|bar)'会找到包含'foo' OR 'bar'的行。

您想要包含 BOTH 'foo' AND 'bar'的行。这些命令中的任何一个都可以:

sed '/foo/!d;/bar/!d' file.log

awk '/foo/ && /bar/' file.log

这两个命令 - 理论上 - 应该cat | grep | grep构造更有效,因为:

  • sedawk都执行自己的文件读取;不需要管道开销
  • 我给上面sedawk的'程序'使用布尔短路来快速跳过不包含'foo'的行,因此只测试包含'foo'的行到/ bar /正则表达式

但是,我还没有测试过它们。 YMMV:)

答案 1 :(得分:2)

理论上,最快的方法应该是:

grep -E '(foo.*bar|bar.*foo)' file.log

出于以下几个原因:首先,grep直接从文件中读取,而不是添加让cat读取它的步骤,并将其填入管道以供grep读取。其次,它只使用一个grep实例,因此文件的每一行只需要处理一次。第三,grep -E通常比大文件上的普通grep更快(但在小文件上更慢),尽管这取决于你的grep实现。最后,grep(在其所有变体中)针对字符串搜索进行了优化,而sed和awk是恰好能够搜索的通用工具(但未针对它进行优化)。

答案 2 :(得分:1)

这两项行动根本不同。这一个:

cat file.log | grep foo | grep bar

在file.log中查找foo,然后在最后一次grep输出中查找bar。而cat file.log | grep -E '(foo|bar)'在file.log中查找foo或bar。输出应该是非常不同的。使用您需要的任何行为。

至于效率,它们并不是真正具有可比性,因为它们做了不同的事情。但两者都应该足够快。

答案 3 :(得分:0)

如果你这样做:

cat file.log | grep foo | grep bar

您只能按任意顺序打印同时包含foobar的行。如果这是你的意图:

grep -e "foo.*bar" -e "bar.*foo" file.log

因为我只需解析输出一次就会更有效率。

注意我不需要cat本身更有效率。您很少需要cat,除非您 concatinating 文件(这是命令的目的)。 99%的情况下,您可以将文件名添加到管道中第一个命令的末尾,或者如果您有tr之类的命令不允许您使用文件,则可以始终重定向输入如下:

tr `a-z` `A-Z` < $fileName

但是,关于无用的cat足够了。我家里有两个。

您可以将多个正则表达式传递给单个grep,这通常比管道多个greps更有效。但是,如果您可以消除正则表达式,您可能会发现这是最有效的:

fgrep "foo" file.log | fgrep "bar"

grep不同,fgrep不解析正则表达式,这意味着它可以更快,更快地解析行。试试这个:

time fgrep "foo" file.log | fgrep "bar"

time grep -e "foo.*bar" -e "bar.*foo" file.log

看看哪个更快。