【问题标题】:Efficient search of several strings in a text file高效搜索文本文件中的多个字符串
【发布时间】:2012-10-05 14:35:15
【问题描述】:

我使用 egrep 在一个非常长的文件(100 万行)中查找多个字符串的完全匹配:

egrep "\<string1\>|<\string2\>" my_file

但是即使只找到两个字符串也需要太多时间。似乎它会沿着文件的总行查找每个字符串,即使它发现了一个事件。 事实上,我知道该文件只包含每个字符串的一次出现。 然后我想知道一旦发现字符串出现,如何强制 egrep 停止查找字符串并查找列表中的下一个。或者如果有另一种方法可以有效地做到这一点。

谢谢。

【问题讨论】:

  • 您要查找多少个字符串?一把还是几千?

标签: bash grep processing-efficiency


【解决方案1】:

-m 选项限制了匹配的数量:

-m NUM, --max-count=NUM
     Stop reading a file after NUM matching lines.

但是,您不能将它直接用于您的复杂模式,因为这样您将只能获得所有子模式的 1 行。你可以做的是循环调用fgrep -m 1的子模式:

for pat in $patterns; do
    fgrep -m 1 $pat my_file
done

附:另一种选择是像您一样使用复杂模式,并指定匹配数等于子模式数,但这会导致每个文件行的比较速度变慢。

【讨论】:

  • 感谢您的回答。我得到了 --max-count=NUM
  • 旁白:鉴于 OP 知道每个字符串每个文件最多出现一次,--max-count=1 的平均加速仅为 200%。
  • 我认为匹配的复杂模式等于子模式的数量实际上是最快的;请参阅我的答案以获得解释。
【解决方案2】:

您应该如何优化搜索取决于您的 grep 实现使用的算法。 egrep 的“传统”算法是将模式编译成确定性有限自动机。如果您不知道那是什么,请不要担心:重要的是编译需要一点时间,但是一旦完成,它就会非常快,而且它的速度并不取决于它正在寻找的模式的复杂性为了。事实上,一旦编译完成,egrep 实际上比 fgrep 快——这意味着 fgrep 在小文件上最快,egrep 在大文件上最快。

至少,[ef]grep 的传统实现是这样的。我认为大多数现代实现都是自适应的,并且会根据情况切换算法(例如,我认为现代 fgreps 将切换到足够大的文件的已编译 DFA 模式)。要找出最适合您的实现的方法,您确实需要尝试一些定时实验。

不过,我可以给您一些建议:首先,避免多次运行搜索(例如,对每个单词运行 fgrep),因为这意味着多次扫描文件。其次,不要担心最小化它正在搜索的字符串数量,因为如果您处于最佳模式,那无论如何都无关紧要。第三,使用@Lev 对-m 的建议使其在找到所需内容后停止(尽管我很确定这将是对-m2 的两个单词的单次搜索)。

【讨论】:

  • 一个非常好的答案,谢谢。让我终于去查找 DFA 的 :)
【解决方案3】:

我不确定,但也许这个更快:

grep -e '<pattern1>' -e '<pattern2>' -e '<pattern3>' your_file

-F 也可能会加快速度,我认为您的模式并不是真正的模式。另外,我认为如果您的输出是彩色的,那么 grep 就别无选择,只能查找所有模式。

【讨论】:

  • 我用字符串替换了单词模式更好:) 我必须使用 egrep 因为我避免循环抛出包含搜索字符串的数组。然后我只是使用参数扩展来获取我所写的。最后使用 egrep 找到这些。
  • 我仍然不确定你为什么需要egrep。怎么比grep -F -e 'string1' -e 'string2' -e 'string3' your_file好。顺便说一句,你试过了吗?
  • 是的,正如 Lev 建议的那样,将 -m 2 添加到此命令行也应该会有所改善,起初我没有意识到每个模式只有一个匹配行,而不是每个模式只有一个模式行。
猜你喜欢
  • 2013-03-02
  • 1970-01-01
  • 2019-10-24
  • 2011-04-28
  • 2012-09-28
  • 2011-04-03
  • 1970-01-01
  • 2012-10-07
  • 1970-01-01
相关资源
最近更新 更多