【问题标题】:grep not performing very well on large files, is there an alternative?grep 在大文件上表现不佳,有替代方案吗?
【发布时间】:2015-01-02 04:24:56
【问题描述】:

我有一个差异,它基本上等同于额外的唯一行或文件中移动的行,因此它们的行号已经改变。为了确定什么是真正的新增内容,我运行了这个小 perl sn-p 以将“已解决”行与“未解决”行分开:

perl -n -e'
    /^\-([^\-].*?)\([^,\(]+,\d+,\d+\).*$/ && do { print STDOUT "$1\n"; next; };
    /^\+([^\+].*?)\([^,\(]+,\d+,\d+\).*$/ && do { print STDERR "$1\n"; next; };
' "$delta" 1>resolved 2>unresolved

事实上,这非常快并且可以完成工作,将 6000+ 行差异分成两个 3000+ 行文件,删除对行号的任何引用和统一差异装饰。接下来是 grep 命令,它似乎以 100% CPU 运行了将近 9 分钟(真实):

grep -v -f resolved unresolved

这实质上是从未解析的文件中删除所有已解析的行。 9 分钟后的输出,巧合的是 9 行输出——唯一的添加或未解决的行。

首先,当我过去使用 grep 时,它在这方面做得非常好,那么为什么在这种情况下它会异常缓慢并且 CPU 很饿?

其次,是否有更有效的替代方法从一个文件中删除包含在另一个文件中的行?

【问题讨论】:

  • 好的,我想我已经用数字回答了我自己的问题。 Grep 正在解析一个文件的 3000 行,可能会解析 3000 次,因此可能相当于解析一个 9,000,000 行的文件。但这仍然不是那么大。这几乎就像 grep 需要 60 秒来解析 1,000,000 行。
  • 注意.*$没用
  • 当然,但我只是想 ^ 如果没有 $ 可能会有点寂寞。 :-)
  • 我认为使用 Regexp::Assemble 构建单个正则表达式而不是大量使用它们会带来好处。

标签: perl awk sed grep


【解决方案1】:

如果要在两个文件中匹配的行应该是完全匹配的,您可以使用 sort 和 uniq 来完成这项工作:

cat resolved resolved unresolved | sort | uniq -u

上述管道中唯一不重复的行将是 unresolved 中未在 resolved 中的行。请注意,在 cat 命令中指定两次 resolved 很重要:否则 uniq 还将挑选出该文件唯一的行。这假设 resolvedunresolved 开始时没有重复的行。但这很容易处理:只需先对它们进行排序和唯一化

sort resolved | uniq > resolved.uniq
sort unresolved | uniq > unresolved.uniq

另外,如果我尝试匹配固定字符串,我发现 fgrep 的速度要快得多,所以这可能是一种替代方法。

【讨论】:

  • cat resolved resolved unresolved 解决方案在 1 秒内有效。我也会试一试 fgrep 解决方案。
  • 不错!这个问题的一个变种是我在采访中偶尔会问到的问题。看到人们想出的东西总是很有趣。
  • fgrep 解决方案似乎稍微快了一点,但幅度不大。这是此解决方案的时间:真实 0m0.220s,用户 0m0.212s,sys 0m0.004s
  • 您可以通过执行以下操作消除两个进程:sort -u resolved resolved unresolved。不错的解决方案!
  • sort -usort | uniq -u 不同,因为 -u 仅显示 uniq 行而不是每行的 uniq 出现
【解决方案2】:

Grep 可能会针对它被告知要查找的每个匹配项完全解析该文件。如果系统上存在“fgrep”,您可以尝试,如果不存在,则可以尝试 grep -F,这会强制 grep 使用 Aho-Corasick 字符串匹配算法 (http://en.wikipedia.org/wiki/Aho%E2%80%93Corasick_string_matching_algorithm),该算法仅尝试同时匹配所有字符串需要对文件进行一次遍历。

【讨论】:

  • 哇,有什么不同。这是 fgrep 解决方案的时间:real 0m0.049s, user 0m0.041s, sys 0m0.009s
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-30
  • 1970-01-01
  • 2012-05-29
  • 2021-12-03
  • 2019-07-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多