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将匹配所有组