使用preg_replace(PHP),我想删除所有水平的空格,除了引号(“”和“)之间的空格(包括转义的引号)
一个示例(正则表达式应在左侧变为右侧):
db.collection.aggregate([
{ "$group": {
"_id": {
"id": { "$toLong": "$id" },
"cate_id": "$cate_id"
},
"count": { "$sum": 1 }
}},
{ "$group": {
"_id": "$_id.id",
"categories": {
"$push": {
"cate_id": "$_id.cate_id",
"count": "$count"
}
}
}}
])
使用another post我想到了:
2 + 2 => 2+2
f( " ") => f(" ")
f("Test \"mystring\" .") => f("Test \"mystring\" .")
f("' ", " ") => f("' "," ")
基本上会向前看,并检查直到字符串末尾(“”和“”)的引号是否相等。
但是,我在转义字符和引号内的引号方面遇到了问题。
\h(?=[^']*(?:'[^']*'[^']*)*$)(?=[^"]*(?:"[^"]*"[^"]*)*$)
我曾考虑过使用否定的后备:" ' test " => The ' causes problem
" \" test " => The \" causes problem
,但无法使其正常工作。下一个正则表达式失败。当字符串包含转义引号时,则不匹配。
(?<!\\)"
答案 0 :(得分:0)
您可以使用
'~(?<!\\\\)(?:\\\\{2})*(?:"[^\\\\"]*(?:\\\\.[^"\\\\]*)*"|\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\')(*SKIP)(*F)|\h+~s'
请参见regex demo
详细信息
(?<!\\)(?:\\{2})*(?:"[^\\"]*(?:\\.[^"\\]*)*"|'[^\\']*(?:\\.[^'\\]*)*')(*SKIP)(*F)
-一个'...'
或"...."
子字符串,其中第一个引号本身并未转义,一旦匹配就被跳过(因此,它们中的任何内容都不会被删除)
(?<!\\)
-当前位置的左侧不得包含\
个字符(?:\\{2})*
-两次反斜杠的零次或更多次重复(?:"[^\\"]*(?:\\.[^"\\]*)*"|'[^\\']*(?:\\.[^'\\]*)*')
-两种选择之一:
"[^\\"]*(?:\\.[^"\\]*)*"
-双引号内的字符串文字"
-双引号[^\\"]*
-除\
和"
以外的0个或更多字符(?:\\.[^"\\]*)*"
-\
的零个或多个重复,后跟任意一个字符(\\.
),然后是"
和{{1}以外的任意0个或更多字符}(\
)[^"\\]*
-或|
-单引号内的字符串文字'[^\\']*(?:\\.[^'\\]*)*'
-省略找到的匹配项并使regex引擎继续搜索下一个从当前regex索引开始的匹配项的PCRE动词(*SKIP)(*F)
-或1个或多个水平空白|\h+
输出:
$strs = ['2 + 2', 'f( " ")', 'f("Test \\"mystring\\" .")', 'f("\' ", " ")'];
$rx = '~(?<!\\\\)(?:\\\\{2})*(?:"[^\\\\"]*(?:\\\\.[^"\\\\]*)*"|\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\')(*SKIP)(*F)|\h+~s';
print_r( preg_replace($rx, '', $strs) );