【问题标题】:Regex vs. string:find() for simple word boundary正则表达式与字符串:find() 用于简单的单词边界
【发布时间】:2011-06-10 01:12:23
【问题描述】:

假设我只需要找出从文件中读取的行是否包含来自有限组单词的单词。

这样做的一种方法是像这样使用regex

.*\y(good|better|best)\y.*

实现此目的的另一种方法是使用这样的代码:

 if ( (readLine.find("good")   != string::npos) ||
      (readLine.find("better") != string::npos) ||
      (readLine.find("best")   != string::npos) )
 {
   // line contains a word from a finite set of words.
 }

哪种方式会有更好的性能? (即速度和 CPU 利用率)

【问题讨论】:

  • 正则表达式对我来说一直都是 - 每个人都知道它,它快速且易于使用。
  • @Chuck 每个人都知道正则表达式吗?这是多么不真实。 :)
  • 这似乎很容易测量和测试

标签: c++ regex performance search


【解决方案1】:

显然不是第二个(使用“find”),因为您正在运行三个比较(需要遍历字符串至少 3 次)而不是一个希望是聪明的比较。如果正则表达式引擎完全按照应有的方式工作(我想确实如此),那么它可能至少快三倍。

【讨论】:

  • 你真的不能不衡量就这么说。如果这些行足够短,它们可能适合单行 CPU 缓存,find 可能会非常快。
  • larsmans - 嗯,是的,理论上,这些发现可能会以某种方式同样快甚至更快。由于问题是性能,“大差异”的情况将是一个很长的字符串。
  • 不一定; “大不同”的情况可能是从内存中的一大块文本中取出许多小行。
  • Seth:不一定,但我的直觉是即使在 CPU 缓存中已经有许多小行的情况下,在它们上运行已编译的正则表达式也会比多次查找更快
【解决方案2】:

在您进行测量之前,您不会知道哪个更快,但关键问题是:

  1. 正则表达式实现,尤其是。是否需要预编译(如 Google RE2、POSIX 正则表达式)。
  2. string::find的实现。
  3. 您正在搜索的字符串的长度。
  4. 您正在搜索多少个字符串。

我的赌注是正则表达式,但同样:你必须测量才能确定。

【讨论】:

    【解决方案3】:

    正则表达式的性能会更好,但去掉那些 '.*' 部分。它们使代码复杂化并且没有任何用途。像这样的正则表达式:

    \y(good|better|best)\y
    

    将一次性搜索字符串。它从这个正则表达式构建的算法将首先查找 \y,然后查找字符 1 (g|b),然后查找字符 2(g => go 或 b => be),字符 3(go => goo 或 be => bes |bet)、字符 4 (go => good or bes => best or bet => bett) 等。无需构建自己的状态机,这将是最快的。

    【讨论】:

    • 哇!到目前为止,我收到的所有答案都很棒,但是恕我直言,这是最好的答案,因为它还简要说明了正则表达式引擎的工作原理和方式。我将不得不接受这个答案(抱歉,我没有足够的分数来投赞成票,否则我会向所有回答我问题的人投赞成票)。
    • 如果您使用像 Google 的 RE2 这样的编译正则表达式引擎,搜索速度可能会在使用和不使用 .* 时相同。
    猜你喜欢
    • 2021-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-31
    • 1970-01-01
    • 1970-01-01
    • 2014-06-07
    • 2012-04-29
    相关资源
    最近更新 更多