空的反向引用导致PHP中的匹配失败...是否有解决方法?

时间:2010-08-11 14:01:24

标签: php regex backreference

我在PHP中使用可能为空的反向引用的正则表达式时遇到问题。我希望它能像http://www.regular-expressions.info/brackets.html中所解释的那样工作:

  

如果没有使用反向引用   特殊匹配尝试(例如   问题的第一个例子   马克做了第一个反向引用   它是空的。运用   正则表达式中的空反对是   非常好。它就是这样   取而代之的是虚无。

然而,似乎PHP与http://php.net/manual/en/regexp.reference.back-references.php

有点不同
  

如果子模式实际上没有   用于特定的比赛,然后任何   对它的反向引用总是失败。

作为一个简单的例子,我希望将以下两个内容与此正则表达式匹配:

  • {something} ... {/ something}
  • {something:else} ... {/ something:else}

提前知道“某事”的地方,“其他”可以是任何事物(或什么都不是)。

所以我尝试了以下正则表达式(“else”硬编码以简化):

preg_match("/\{(something(:else)?)\}(.*?)\{\/something\\2\}/is", $data, $matches)

不幸的是如果(:else)?不匹配,\ 2反向引用失败。如果我使\ 2可选(\ 2?),那么我可能会匹配{something} ... {something:else},这是不好的。

我是否遇到了正则表达式的限制(臭名昭着的“你需要一个解析器,而不是一个正则表达式”)或者这是否可以修复?

测试程序:

<?php
    $data = "{something} ... {/something}
             {something:else} ... {/something:else}
             {something:else} ... {/something}";

    // won't match {something} ... {/something}
    preg_match_all("/\{(something(:else)?)\}(.*?)\{\/something\\2\}/is", $data, $matches);
    print_r($matches);

    // change \\2 to \\2? and it matches too much
    preg_match_all("/\{(something(:else)?)\}(.*?)\{\/something\\2?\}/is", $data, $matches);
    print_r($matches);
?>

3 个答案:

答案 0 :(得分:2)

嗯,为什么不更换?用?或

更改

"/\{(something(:else)?)\}(.*?)\{\/something\\2\}/is"

"/\{(something(:else|))\}(.*?)\{\/something\\2\}/is"

这样一直会捕获引用,但它有时会为空(这没关系)......

答案 1 :(得分:1)

为什么不简单地使用\ 1代替\ 2?

preg_match_all("/\{(something(:else)?)\}(.*?)\{\/\\1\}/is", $data, $matches);

对于“你需要一个解析器”问题,你需要/它需要它来解析嵌套的构造。

答案 2 :(得分:0)

在这类案件的下一课(如 {something} ... {/ something}或{something} ... {something} ... {/ something} {/ something}  和更多。 SL5_ preg_contentFinder

的示例

https://gist.github.com/sl5net/7029093#file-sl5_preg_contentfinder-php

        $content1 = $content = '`ha <!--[01.o0]-->1<!--[/01.o0]-->

嗨[02.o0] 2 浩3 `';

            $pos_of_next_search = 0;
        $begin = '(<!--)?\[([^\]>]*\.o0)\](-->)?';
        $end = '<!--\[\/($2)\]-->';
        $cf = new SL5_preg_contentFinder($content);
        $cf->setBeginEnd_RegEx($begin, $end);
        $cf->setSearchMode('use_BackReference_IfExists_()$1${1}');
        $loopCount = 0;
        while ($loopCount++ < 5) {
            $cf->setPosOfNextSearch($pos_of_next_search);
            list($findPos['begin_begin'], $findPos['end_begin'],
                $findPos['begin_end'], $findPos['end_next'], $matchesReturn) = $cf->get_borders_left(__LINE__);
            $content = $cf->getContent();
            $expectedContent = $maxLoopCount;
            if ($maxLoopCount>3)$expectedContent = '';
            if ($content != $expectedContent)
                die(__LINE__ . 'ERROR :   $content != $expectedContent :' . " '$content'!= '$expectedContent ");
            if (is_null($findPos['begin_begin'])) {
                break;
            }
            echo(__LINE__ . ': '.$content1.' ==> "' . $content . '"');

            $pos_of_next_search = $findPos['end_next'];
        }
相关问题