PHP:PCRE:preg_match_all在模式中不匹配转义的美元符号($)

时间:2015-01-28 22:22:05

标签: php regex pcre

我正在尝试匹配子字符串的所有实例' $ {foo}'里面$ content。我可以匹配' {foo}'但不是' $ {foo}'由于某些原因。谁知道为什么?

$content="aaaa\${foo}bbbb\n";
echo $content; // aaaa${foo}bbbb

// THIS WORKS AS EXPECTED: matches all instances of substring '{foo}'
$result = preg_match_all("/(\{\w+\})/", $content, $matches);
if ($result === false) { die("NOT OK!"); }
echo "NUMBER OF MATCHES: ", $result, "\n";
var_dump($matches);

// THIS DOESN'T WORK AS EXPECTED: doesn't match instances of substring '${foo}'
$result = preg_match_all("/(\$\{\w+\})/", $content, $matches);
if ($result === false) { die("NOT OK!"); }
echo "NUMBER OF MATCHES: ", $result, "\n";
var_dump($matches);

以下是此代码的输出。第一部分输出1匹配,如预期,而第二部分输出0匹配,但我期待1匹配:

aaaa${foo}bbbb
NUMBER OF MATCHES: 1
array(2) {
  [0]=>
  array(1) {
    [0]=>
    string(5) "{foo}"
  }
  [1]=>
  array(1) {
    [0]=>
    string(5) "{foo}"
  }
}
NUMBER OF MATCHES: 0
array(2) {
  [0]=>
  array(0) {
  }
  [1]=>
  array(0) {
  }
}

感谢。

3 个答案:

答案 0 :(得分:2)

你需要双击反斜杠(你也应该双重转义大括号)。

"/(\\$\\{\w+\\})/"

这是因为你需要转义字符串解析器的反斜杠,因为\\在PCRE甚至可以看到字符串之前变为\。如果没有双重转义,PCRE将获得$,这显然会尝试匹配字符串的结尾。

答案 1 :(得分:2)

使用单引号,以便不必双重转义$符号。只有正则表达式特殊字符在单引号中的正则表达式中使用时才需要转义,除了需要在单引号括起的任何PHP字符串中转义的反斜杠和单引号。使用正则表达式时,只需在正则表达式中嵌入变量时使用双引号(在这种情况下,其他字符可能需要转义以及其他答案演示)。

因此以下工作:

$content="aaaa\${foo}bbbb\n";
echo $content; // aaaa${foo}bbbb

// THIS WORKS AS EXPECTED: matches all instances of substring '{foo}'
$result = preg_match_all('/(\{\w+\})/', $content, $matches);
if ($result === false) { die("NOT OK!"); }
echo "NUMBER OF MATCHES: ", $result, "\n";
var_dump($matches);

// THIS ALSO WORKS AS EXPECTED: matches all instances of substring '${foo}'
$result = preg_match_all('/(\$\{\w+\})/', $content, $matches);
if ($result === false) { die("NOT OK!"); }
echo "NUMBER OF MATCHES: ", $result, "\n";
var_dump($matches);

答案 2 :(得分:0)

在模式上使用单引号。

示例:

$pattern = '/(AUTH|PENALTY|(?:\$LINE))/i';
$DETTYPE_VALUE = array_filter($data, function($a) use($pattern)  {
    return preg_match_all($pattern, $a['fine']);
});