PHP正则表达式无法正常工作 - 在本地服务器上返回NULL,但在其他服务器上正常工作

时间:2012-03-17 20:13:57

标签: php regex

我有以下正则表达式:

/\{\s?joomla-tag\s+(.*<+.+>+.*)\s?\}/is

和以下代码:

$regex = "/\{\s?joomla-tag\s+(.*<+.+>+.*)\s?\}/is";
$replace = '<div class="someclass">$1</div>';
$text = preg_replace( $regex, $replace, $text );

但是,遗憾的是,它无法与以下代码匹配(尽管如此):

.... many html lines .......
<p>123{joomla-tag Lore<strong>m</strong> ip</p>
<p>sum dolor sit amet}</p>
.... many html lines .......

查看真实示例: http://pastebin.com/WSQyrmxd

出了什么问题:正则表达还是其他什么?你能告诉你正确的变体吗? 在RegExr中,一切都很顺利,但不是在PHP中。

在本地服务器上,我只是在preg_replace

之后得到NULL

修改 最后我找到了一个解决方案:(谢谢, sg3s ,一个想法) http://www.pelagodesign.com/blog/2008/01/25/wtf-preg_replace-returns-null/

3 个答案:

答案 0 :(得分:5)

你说你解决了这个问题,但如果你的解决方案是增加backtrack_limit设置,那不是解决方案。事实上,你可能会在以后为更大的问题做好准备。你需要找出为什么它正在进行如此多的回溯。

\{\s?joomla-tag\s+找到代码的开头后,第一个.*最初会吞噬文档的其余部分。然后它开始后退,试图让正则表达式的其余部分匹配。当它到达<+可以匹配的点时,.+会再次消耗文档的其余部分,并开始另一波回溯。在此之后又有了.*,你正在做一些荒谬的不必要的工作。

这是经验法则的原因,

  

如果您可以使用更具体的内容,请勿使用点元字符(尤其是.*.+)。如果您使用点,请不要在单行或DOTALL模式下使用它(即/s修饰符或其内联,(?s)形式。

在这种情况下,您知道匹配应该在下一个右大括号(})结束,所以在此之前不要让它匹配任何大括号:

\{\s?joomla-tag\s+([^}]*)\}

答案 1 :(得分:4)

由于PCRE正则表达式引擎耗尽堆栈,这听起来可能是:pcre.recursion_limit错误。我以前见过这个(但通常症状更严重 - 即完全崩溃网络服务器!)请注意,这类问题经常会在本地服务器而不是远程服务器上出现症状,特别是在本地系统运行Apache时在Windows下(httpd.exe的Win32版本只有256KB的堆栈空间)。

preg_replace()在PCRE库中遇到错误时返回NULL。您可以使用preg_last_error()函数来获取上一个错误并打印出如下消息:

   $pcre_err = preg_last_error();  // PHP 5.2 and above.
    if ($pcre_err === PREG_NO_ERROR) {
        $msg = 'Successful non-match.';
    } else {
        // preg_match error!
        switch ($pcre_err) {
            case PREG_INTERNAL_ERROR:
                $msg = 'PREG_INTERNAL_ERROR';
                break;
            case PREG_BACKTRACK_LIMIT_ERROR:
                $msg = 'PREG_BACKTRACK_LIMIT_ERROR';
                break;
            case PREG_RECURSION_LIMIT_ERROR:
                $msg = 'PREG_RECURSION_LIMIT_ERROR';
                break;
            case PREG_BAD_UTF8_ERROR:
                $msg = 'PREG_BAD_UTF8_ERROR';
                break;
            case PREG_BAD_UTF8_OFFSET_ERROR:
                $msg = 'PREG_BAD_UTF8_OFFSET_ERROR';
                break;
            default:
                $msg = 'Unrecognized PREG error';
                break;
        }
    }
    echo($msg);

我已经通过对相关问题的回答详细解释了这个错误。参见:

RegExp in preg_match function returning browser error

PHP regex: is there anything wrong with this code?

Minifying final HTML output using regular expressions with CodeIgniter

祝你好运!

答案 2 :(得分:2)

works for me

请注意,从HTML的角度来看,您的替代品不会创建有效的结构。

使用全文

即使使用提供的完整HTML示例,它仍然是works for me。所以你的其他代码必须有一些错误;您可能希望启用完整错误输出以查看是否存在其他问题。