PHP:正则表达式,用于忽略引号内的转义引号

2022-08-30 13:48:32

在发布此内容之前,我查看了相关问题,我无法修改任何相关答案以使用我的方法(不擅长正则表达式)。

基本上,这是我现有的行:

$code = preg_replace_callback( '/"(.*?)"/', array( &$this, '_getPHPString' ), $code );

$code = preg_replace_callback( "#'(.*?)'#", array( &$this, '_getPHPString' ), $code );

它们都匹配 和 之间包含的字符串。我需要正则表达式忽略它们之间包含的转义引号。所以数据之间的会忽略,而数据之间的会忽略。''""''\'""\"

任何帮助将不胜感激。


答案 1

对于大多数字符串,您需要允许转义的任何内容(而不仅仅是转义引号)。例如,您很可能需要允许转义字符,例如和当然,转义转义:。"\n""\t""\\"

这是一个经常被问到的问题,很久以前就已经解决(和优化)了。Jeffrey Friedl在他的经典著作《掌握正则表达式》(第3版)中深入探讨了这个问题(作为一个例子)。这是您要查找的正则表达式:

好:

"([^"\\]|\\.)*"
版本1:工作正常,但效率不是很高。

更好:

"([^"\\]++|\\.)*"
版本2:如果你有所有格量词或原子群,效率更高(参见:使用原子群方法的sin的正确答案)。"((?>[^"\\]+)|\\.)*"

最好:

"[^"\\]*(?:\\.[^"\\]*)*"
版本3:仍然更有效率。实现 Friedl 的“展开循环”技术。不需要所有格或原子组(即这可以在Javascript和其他功能较少的正则表达式引擎中使用。

以下是 PHP 语法中推荐的正则表达式,用于双引号和单引号子字符串:

$re_dq = '/"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"/s';
$re_sq = "/'[^'\\\\]*(?:\\\\.[^'\\\\]*)*'/s";

答案 2

尝试像这样一个正则表达式:

'/"(\\\\[\\\\"]|[^\\\\"])*"/'

一个(简短的)解释:

"                 # match a `"`
(                 # open group 1
  \\\\[\\\\"]     #   match either `\\` or `\"`
  |               #   OR
  [^\\\\"]        #   match any char other than `\` and `"`
)*                # close group 1, and repeat it zero or more times
"                 # match a `"`

以下代码段:

<?php
$text = 'abc "string \\\\ \\" literal" def';
preg_match_all('/"(\\\\[\\\\"]|[^\\\\"])*"/', $text, $matches);
echo $text . "\n";
print_r($matches);
?>

生产:

abc "string \\ \" literal" def
Array
(
    [0] => Array
        (
            [0] => "string \\ \" literal"
        )

    [1] => Array
        (
            [0] => l
        )

)

正如您在Ideone上看到的那样


推荐