使用preg_replace(PHP)我想删除所有水平空格,除了在引号(“”和“)之间找到的空格(包括转义引号)
一个例子(正则表达式应该在右侧转左侧):
2 + 2 => 2+2
f( " ") => f(" ")
f("Test \"mystring\" .") => f("Test \"mystring\" .")
f("' ", " ") => f("' "," ")
使用another post,我想出了:\h(?=[^']*(?:'[^']*'[^']*)*$)(?=[^"]*(?:"[^"]*"[^"]*)*$)
这基本上是向前看并检查在字符串结尾之前是否有均匀的引号(“”和“”)。
但是,我在转义字符和引号内的引号方面存在问题。
" ' test " => The ' causes problem
" \" test " => The \" causes problem
我曾想过使用负面的lookbehinds:(?<!\\)"
但无法让它工作。下一个正则表达式失败了。当字符串包含转义引号时,它不匹配。
\h(?=[^"]*(?:(?<!\\)"(?:[^"]*?(?<!\\)")[^"]*?)*$)
你可以用
'~(?<!\\\\)(?:\\\\{2})*(?:"[^\\\\"]*(?:\\\\.[^"\\\\]*)*"|\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\')(*SKIP)(*F)|\h+~s'
细节
(?<!\\)(?:\\{2})*(?:"[^\\"]*(?:\\.[^"\\]*)*"|'[^\\']*(?:\\.[^'\\]*)*')(*SKIP)(*F)
- 一个'...'
或"...."
子字符串,其中第一个引号本身不会被转义,一旦匹配就会被跳过(因此,它们内部的任何内容都不会被删除)
(?<!\\)
- 没有\
字符立即允许在当前位置的左侧
(?:\\{2})*
- 零反复重复双反斜杠
(?:"[^\\"]*(?:\\.[^"\\]*)*"|'[^\\']*(?:\\.[^'\\]*)*')
- 两种选择中的任何一种:
"[^\\"]*(?:\\.[^"\\]*)*"
- 双引号内的字符串文字
"
- 双引号
[^\\"]*
- 除了\
和"
之外的0个或更多字符
(?:\\.[^"\\]*)*"
- \
的零次或多次重复,然后是任何字符(\\.
),然后是"
和\
([^"\\]*
)以外的任何0或更多字符
|
- 或
'[^\\']*(?:\\.[^'\\]*)*'
- 单引号内的字符串文字
(*SKIP)(*F)
- PCRE动词,省略找到的匹配并使正则表达式引擎继续搜索从当前正则表达式索引开始的下一个匹配|\h+
- 或1个或多个水平空格$strs = ['2 + 2', 'f( " ")', 'f("Test \\"mystring\\" .")', 'f("\' ", " ")'];
$rx = '~(?<!\\\\)(?:\\\\{2})*(?:"[^\\\\"]*(?:\\\\.[^"\\\\]*)*"|\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\')(*SKIP)(*F)|\h+~s';
print_r( preg_replace($rx, '', $strs) );
输出:
Array
(
[0] => 2+2
[1] => f(" ")
[2] => f("Test \"mystring\" .")
[3] => f("' "," ")
)