2014-09-21 78 views
1

我写了一个正则表达式模式,当我在Regexr中测试它时,它完美地工作,但是当我在我的PHP代码中使用它时,它并不总是匹配。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-]+)在逆向引用造成的,但是,我不能一刀弄清楚如何解决这个。

回答

2

因为您指的是一个不存在的组(组2)。所以从正则表达式中删除\2

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

DEMO

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

我喜欢,你怎么说明吧:) – 2014-09-21 16:30:00

+0

谢谢,你和@hwnd帮我弄明白了。 – CupOfTea696 2014-09-21 21:26:06

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" 
} 
+0

问题是这样'~~~ lang {class} lang'也给出了一个匹配,它不应该。 – CupOfTea696 2014-09-21 21:15:22

+0

我刚刚解决了它,我把第二个捕获组更改为'([\ w - ] *)',当它不在那里而不是不存在时,它是一个空字符串。 – CupOfTea696 2014-09-21 21:25:27

+0

告诉我它应该完全匹配,当我回家时我会看一下 – hwnd 2014-09-21 21:35:21

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);