PHP正则表达式反向引用不起作用

时间:2014-09-21 15:50:36

标签: php regex

我编写了一个正则表达式模式,当我在Regexr中测试它时效果很好,但是当我在我的PHP代码中使用它时它并不总是匹配它应该匹配。

The regular expression,包括应该和不应匹配的一些示例。

应该匹配但不匹配的示例PHP代码:

preg_match('/^([~]{3,})\s*([\w-]+)?\s*(?:\{([\w-\s]+)\})?\s*(\2[\w-]+)?\s*$/', "~~~ {class} lang", $matches);
echo var_dump($matches);

我认为问题是由最后一个捕获组(\2[\w-]+)中的反向引用引起的,但是,我无法知道如何解决这个问题。

3 个答案:

答案 0 :(得分:2)

因为您指的是不存在的组(组2)。因此,请从正则表达式中删除\2

^([~]{3,})\s*([\w-]+)?\s*(?:\{([-\w\s]+)\})?\s*([\w-]+)?\s*$

DEMO

    ~~~  {class} lang
     |  |   |      |
  Group1| Group3 Group4
        |
Missing group 2

答案 1 :(得分:2)

问题是由捕获组#2引起的,您已将此组设为可选。因此,既然它可能存在,也可能不存在,你需要使你的反引用也是可选的,否则它总是寻找一个必需的组。

但是,由于所有组都是可选的,我只会递归第二组的子模式。

^(~{3,})\s*([\w-]+)?\s*(?:{([^}]+)})?\s*((?2))?\s*$

示例:

$str = '~~~ {class} lang';
preg_match('/^(~{3,})\s*([\w-]+)?\s*(?:{([^}]+)})?\s*((?2))?\s*$/', $str, $matches);
var_dump($matches);

输出

array(5) {
  [0]=> string(16) "~~~ {class} lang"
  [1]=> string(3) "~~~"
  [2]=> string(0) ""                   # Returns "" for optional groups that dont exist
  [3]=> string(5) "class"
  [4]=> string(4) "lang"
}

答案 2 :(得分:0)

下面的答案帮助我弄清楚它为什么不起作用。然而,这两个答案都会给$str = '~~~ lang {class} lang';带来正面匹配,这是我不想要的。 我修改了我的更改捕获组2到([\w-]*),这样即使在那个地方没有字符串,捕获组仍然存在但仍然是空的。这样所有以下字符串都匹配:

$str = '~~~   lang      {no-lines float left}   ';
$str = '~~~     {class}   ';
$str = '~~~ lang';
$str = '~~~ {class } lang ';
$str = '~~~';
$str = '~~~lang{class}';

但是这个赢了:

$str = '~~~ css {class} php';

完整解决方案:

$str = '~~~ {class} lang';
preg_match('/^([~]{3,})\s*([\w-]*)?\s*(?:\{([\w-\s]+)\})?\s*(\2[\w-]+)?\s*$/', $str, $matches);
var_dump($matches);