【问题标题】:preg_match_all( ) behaves differently on different serverspreg_match_all( ) 在不同的服务器上表现不同
【发布时间】:2012-10-06 16:04:48
【问题描述】:

以下代码在我的 PC 上的 XAMPP 上完美运行,但在我新购买的 VPS 上却无法运行。它使我的代码崩溃了。

preg_match_all( "/$regex/siU" , $string , $matches , PREG_SET_ORDER );

这应该只是从 HTML 中获取链接和标题。

以前,今天发生了类似的正则表达式问题。代码在本地服务器上运行良好,但在 vps 上创建“连接被重置”错误。该问题是由使用以下代码删除的一些注释 html(其中包含 php 代码)以优化输出引起的,但即使连接重置问题得到解决,HTML 仍然在浏览器源中有 cmets。

$string = preg_replace( '/<!--(.|\s)*?-->/' , ''    , $string );

所以,问题很明显。这些正则表达式函数无法正常工作。但我不知道解决方案。

谁能帮我解决这个问题。

已解决:

感谢https://stackoverflow.com/a/12761686/369005@vimishor

【问题讨论】:

  • phpinfo() 显示配置命令 '--with-pcre-regex=/opt/pcre' 因此安装了 PCRE。
  • 跟服务器日志有关系吗?
  • configure命令与它关系不大;您需要找出进程死亡的原因.. 似乎您的 pcre 存在一些链接问题。
  • Apache 错误日志文件为空。在 /var/log/httpd/ 中看到使用 vim error_log
  • 再看一遍问题,我可能理解错了; “连接重置”发生是因为正则表达式没有正确应用?您正在对实际在您的服务器上运行的 HTML 执行正则表达式?!

标签: php regex


【解决方案1】:

众所周知,PCRE 有时在处理超过 200 行的文本时会出现一些问题。过去,来自 Drupal 和 GeSHi 的开发人员遇到过这个问题。

参考资料:

  1. Drupal PCRE Issue @ March 23, 2012
  2. GeSHi PCRE Issue @ February 02, 2012

如果您可以将文本分成小块(例如 100 行)并在每个块上运行正则表达式,可能会有所帮助。

【讨论】:

  • 好的,让我试试。我会尽快回复结果。
  • 在应用正则表达式之前添加了此代码。依然没有。 $string = str_replace( array( "\r" , "\n" ) , " " , $string );
  • 您将 Mac 风格的行尾替换为 Unix 风格的行尾。我的建议是只选择前 100 行文本并仅在这些行上运行正则表达式;重复此过程,直到完成整个文本。
  • 上面的例子用空格替换了mac和unix风格的新行。而且,这解决了这个问题。你是对的。问题出在上面提到的 PCRE 问题上。感谢您的回答。
  • 啊,你是对的。我错过了str_replace 里面的array()。对此感到抱歉。我很高兴你解决了这个问题。最好的问候。
【解决方案2】:

让我在此稍等片刻。使用正则表达式解析 HTML 是个坏主意,除非它是格式错误的文档中非常孤立的问题。您将需要使用适当的解析器;例如,这是一个去除 HTML cmets 的示例:

$html = <<<EOM
<html>
<body>
<div id="test">
<!--
comment here
-->
</div>
</body>
</html>
EOM;

$d = new DOMDocument;
$d->loadHTML($html);

$x = new DOMXPath($d);

foreach ($x->query('//comment()') as $node) {
        $node->parentNode->removeChild($node);
}

echo $d->saveHTML();

【讨论】:

  • 很好的例子。但是,即使我实现了这段代码,问题仍然存在。问题出在所有 PCRE 函数上。
  • @HamidSarfraz 你还没有给出一个例子,说明它何时会给出不同的结果,包括来自两个服务器的输入、表达式和输出。
  • 好的,这将需要很长的帖子,所以我将用我认为有用的所有细节来回答下面的问题。请稍等。
  • 谢谢杰克。这个问题已经解决。谢谢您的合作。请继续帮助像我这样的新人。
【解决方案3】:

所以根本问题是应该删除 HTML cmets 的代码不起作用?这可能是因为应该与 cmets 匹配的正则表达式使用 (.|\s)* 来解决 . 不匹配换行符的事实。正如 this answer 解释的那样,这几乎肯定会导致问题。

匹配任何内容(包括换行符)的正确方法是使用 s 修饰符。例如:

'/<!--.*?-->/s'

这将打开单行模式(也称为 DOTALL 模式),它允许 . 匹配换行符。 (其他问题的作者必须改用 [\S\s],因为 JavaScript 没有等效的单行/DOTALL 模式。)

【讨论】:

    【解决方案4】:

    看来问题是您误解了 html cmets 的作用。根据您在问题下方的评论,问题是没有删除html cmets,导致php以错误的参数运行。

    但是,html cmets 对正在运行或未运行的 php 代码没有影响,只会影响浏览器显示的内容(并在 javascript 的情况下运行)。您的 php 代码在输出到达浏览器之前运行。

    如果你想注释掉 php 代码,你需要放入一个/* */ 块或以// 开始每一行。

    【讨论】:

    • 也许我没有解释清楚。让我们再试一次。假设 cmets 上面的第二个正则表达式函数应该删除包括 php 代码的 cmets。但是,在 VPS 上,它并没有做它应该做的事情。保持 cmets 和 php 代码完好无损。现在,想象一下 代码调用了一个没有在任何地方声明的函数(从包含的函数中删除)。出于参考目的,没有删除 php 代码,或者我可以看到脚本过去的样子。而且也没有安全风险,因为它不会执行。
    • @Hamid Sarfraz 如果您使用正则表达式解析 php 脚本,那么您是对的,我的回答不适用。我以为你在解析 html 页面。
    【解决方案5】:

    试试这个:

    $string = preg_replace( '/.*<!--(.|\s)*?-->.*/' , ''    , $string );
    

    一些正则表达式实现会像这样执行您的正则表达式:/^&lt;!--(.|\s)*?--&gt;$/。所以你的表达式在不同的服务器上可能会有不同的表现。

    【讨论】:

    • 如果您使用 matches() 方法,则仅适用于 Java。 PCRE 没有。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-11
    相关资源
    最近更新 更多