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


PHP: PCRE: preg_match_all won't match escaped dollar sign ($) within pattern

我正在尝试匹配$content内子字符串"${foo}"的所有实例。出于某种原因,我可以匹配"{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) {
  }
}

谢谢。

您需要对反斜杠进行双重转义(并且您也应该对大括号进行双重转义)。

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

这是因为您需要转义字符串解析器的反斜杠,因为''在 PCRE 看到字符串之前'。如果没有双重转义,PCRE 只会得到$,这显然会尝试匹配字符串的末尾。

使用单引号,这样就不必对 $ 符号进行双重转义。在正则表达式中使用单引号时,只有正则表达式特殊字符需要转义,反斜杠和单引号除外,反斜杠和单引号需要在任何括在单引号中的 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);

在模式上使用单引号。

例:

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