PHP:正则expression式忽略引号内的转义引号

在发布之前,我查看了相关的问题,我无法修改任何相关的答案来处理我的方法(不擅长正则expression式)。

基本上,这里是我现有的线路:

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

它们都匹配''""之间''string。 我需要正则expression式来忽略它们之间包含的转义引号。 因此, ''之间''数据将忽略\'''之间''数据将忽略\"

任何帮助将不胜感激。

对于大多数string,你需要允许任何东西 (不只是转义报价)逃脱。 例如,您很可能需要允许像"\n""\t"这样的转义字符,当然还有转义字符"\\"

这是一个经常被问到的问题,而且很久以前就已经解决(和优化)了。 Jeffrey Friedl在他的经典着作“ Mastering Regular Expressions(3rd Edition)”中深入地讨论了这个问题(作为例子) 。 这是你正在寻找的正则expression式:

好:

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

更好:

"([^"\\]++|\\.)*" or "((?>[^"\\]+)|\\.)*"
版本2:如果您有占有量词或primefaces组(请参阅:使用primefaces组方法的正确答案),效率更高。

最好:

"[^"\\]*(?:\\.[^"\\]*)*"
版本3:效率更高。 实现Friedl's: “展开循环”技术。 不需要所有格或primefaces组(即可以在Javascript和其他function较less的正则expression式引擎中使用)。

下面是PHP语法中用于双引号和单引号的子string的推荐正则expression式:

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

尝试像这样的正则expression式:

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

一个(简短的)解释:

 " # 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上看到的那样

这似乎与展开的循环一样快,基于一些粗略的基准,但是更容易阅读和理解。 首先它不需要任何回溯。

 "[^"\\]*(\\.[^"\\]*)*" 

这有可能性:

/"(?>(?:(?>[^"\\]+)|\\.)*)"/

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

这会把报价留在外面

 (?<=['"])(.*?)(?=["']) 

并使用global / g将匹配所有组