用于匹配单引号字符串的正则表达式在PHP中失败

时间:2018-07-02 02:07:20

标签: php regex pcre

所以我有这个正则表达式:

/'((?:[^\\']|\\.)*)'/

它应该匹配单引号字符串,而忽略内部的转义单引号\'

works here,但是当executed with PHP时,我得到不同的结果。为什么会这样?

2 个答案:

答案 0 :(得分:3)

使用负向后看可能会更容易。还要注意,您需要两次转义斜线-一次告诉PHP您想要一个文字反斜杠,然后再次告诉正则表达式引擎您想要一个文字反斜杠。

还请注意,您的捕获表达式(.*是贪婪的-它将捕获'个字符之间的所有内容,包括其他'个字符,无论是否已转义。如果您希望它在第一个未转义的'之后停止,请改用.*?。我在下面的示例中使用了非贪婪版本。

<?php

$test = "This is a 'test \' string' for regex selection";
$pattern = "/(?<!\\\\)'(.*?)(?<!\\\\)'/";

echo "Test data: $test\n";
echo "Pattern:   $pattern\n";

if (preg_match($pattern, $test, $matches)) {
    echo "Matches:\n";
    var_dump($matches);
}

答案 1 :(得分:3)

这有点难逃。尽管事实上已经有一个可接受的答案,但原始模式实际上更好。为什么?它允许使用 展开Jeffery Friedl在“精通正则表达式”:"([^\\"]*(?:\\.[^\\"]*)*)"(适用于单引号)中描述的循环技术

Demo

展开循环(使用双引号)

"                              # the start delimiter
 ([^\\"]*                      # anything but the end of the string or the escape char
         (?:\\.                #     the escape char preceeding an escaped char (any char)
               [^\\"]*         #     anything but the end of the string or the escape char
                      )*)      #     repeat
                             " # the end delimiter

这不能解决逃跑的地狱,但您也已在这里被覆盖:

Sample Code

$re = '/\'([^\\\\\']*(?:\\\\.[^\\\\\']*)*)\'/';
$str = '\'foo\', \'can\\\'t\', \'bar\'
\'foo\', \' \\\'cannott\\\'\\\\\', \'bar\'
';

preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);
var_dump($matches);