正则表达式(PHP)删除引号(“”和“”)之间的所有水平空白(包括转义引号)

时间:2019-03-19 15:31:04

标签: php regex preg-replace removing-whitespace

使用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 ,但无法使其正常工作。下一个正则表达式失败。当字符串包含转义引号时,则不匹配。

(?<!\\)"

1 个答案:

答案 0 :(得分:0)

您可以使用

'~(?<!\\\\)(?:\\\\{2})*(?:"[^\\\\"]*(?:\\\\.[^"\\\\]*)*"|\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\')(*SKIP)(*F)|\h+~s'

请参见regex demo

详细信息

  • (?<!\\)(?:\\{2})*(?:"[^\\"]*(?:\\.[^"\\]*)*"|'[^\\']*(?:\\.[^'\\]*)*')(*SKIP)(*F)-一个'...'"...."子字符串,其中第一个引号本身并未转义,一旦匹配就被跳过(因此,它们中的任何内容都不会被删除)
    • (?<!\\)-当前位置的左侧不得包含\个字符
    • (?:\\{2})*-两次反斜杠的零次或更多次重复
    • (?:"[^\\"]*(?:\\.[^"\\]*)*"|'[^\\']*(?:\\.[^'\\]*)*')-两种选择之一:
      • "[^\\"]*(?:\\.[^"\\]*)*"-双引号内的字符串文字
      • "-双引号
      • [^\\"]*-除\"以外的0个或更多字符
      • (?:\\.[^"\\]*)*"-\的零个或多个重复,后跟任意一个字符(\\.),然后是"和{{1}以外的任意0个或更多字符}(\
      • [^"\\]*-或
      • |-单引号内的字符串文字
    • '[^\\']*(?:\\.[^'\\]*)*'-省略找到的匹配项并使regex引擎继续搜索下一个从当前regex索引开始的匹配项的PCRE动词
  • (*SKIP)(*F)-或1个或多个水平空白

PHP demo

|\h+

输出:

$strs = ['2 + 2', 'f( " ")', 'f("Test \\"mystring\\" .")', 'f("\' ",   " ")'];
$rx = '~(?<!\\\\)(?:\\\\{2})*(?:"[^\\\\"]*(?:\\\\.[^"\\\\]*)*"|\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\')(*SKIP)(*F)|\h+~s';
print_r( preg_replace($rx, '', $strs) );