【问题标题】:Why does preg_match_all poop out after so many characters?为什么 preg_match_all 在这么多字符之后会弹出?
【发布时间】:2010-07-16 02:03:15
【问题描述】:

我的 preg_match_all 语句有问题。它一直在完美地工作,因为我一直在输入一篇文章,但是在它经过一定长度后突然停止工作。这是函数的一个已知问题,在这么多字符之后它什么都不做任何事情

$number = preg_match_all("/(<!-- ([\w]+):start -->)\n?(.*?)\n?(<!-- \\2:stop -->)/s", $data, $matches, PREG_SET_ORDER);

它一直运行良好,并且在其他页面上运行良好,但是一旦那篇文章超过了一定的长度,噗,它就停止了对那篇文章的工作。我可以使用另一种解决方案来使其适用于更长的文本块吗?正在处理的文章长度约为 33,000 个字符(包括空格)。

我以前问过这样的问题,但只得到了一个我从未实际测试过的答案。上一次我刚刚找到了另一种方法来解决这个特定场景,但是这次没有办法解决它,因为它都是一篇文章。我尝试将pcre.backtrack_limitpcre.recursion_limit 更改为甚至500,000,但完全没有效果。关于为什么会发生这种情况以及我可以做些什么来让它继续工作,即使是这些大量的文本块,还有其他想法吗? 30,000 个字符的限制似乎有点低,只有 5,000-6,000 个字(这个大约是 5,700 个)。在这里将其分开并不是一个真正的选择,因为如果它们位于两个单独的文本块中,它将无法找到开始和停止。

【问题讨论】:

  • 当它“停止工作”时究竟会发生什么?错误返回?默契失败?挂断 100% CPU? (我认为您可能已经编写了一个正则表达式,它触发了 PCRE 匹配算法的指数最坏情况行为,但没有细节我无法确定。)
  • 它什么也不做,它只是返回0,没有错误或任何东西。
  • 你检查过preg_last_error()吗?不记得我做过那个。
  • @mvds:是的,它什么也不返回 (0)。
  • 32,767 是 16 位有符号整数的最大值。

标签: php limit preg-match-all


【解决方案1】:

我曾经碰到过这个问题,当时我唯一能解决的方法就是拆分字符串。你可以explode()preg_split()

引用我的源代码:

    // regexps have failed miserably on very large tables...
    $parts = explode("<table",$html);

但这是两年前的事了。

【讨论】:

    【解决方案2】:

    看起来您正在使用 HTML。您可能需要考虑使用各种解析器之一。例如,DOM 有a specific class for comments,所以我们知道它可以与它们一起工作。不幸的是,使用 DOM 有点尴尬。

    另一种选择可能是使用XMLReader,它将XML 作为流读取,并将其作为令牌处理。它似乎明白什么是 cmets。我自己从未使用过它,所以我无法告诉你它的效果如何。 (您可以使用 DOM 的 loadHTMLsaveXML 方法将您的 HTML 转换为 XML,假设它的格式不是太可怕。)

    最后,您可以考虑为您的自定义 cmets 编写分词器或解析器。这应该不会太难,而且可能比学习我指出的任何一种 XML 解决方案更快。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-13
      • 1970-01-01
      • 1970-01-01
      • 2014-08-23
      • 1970-01-01
      相关资源
      最近更新 更多