首页 > 解决方案 > 正则表达式 (PHP) 删除除引号之间的所有水平空格(“”和 '')(包括转义引号)

问题描述

使用 preg_replace (PHP) 我想删除所有水平空格,除了引号之间的空格(“”和 '')(包括转义引号)

一个例子(正则表达式应该在右侧转向左侧):

2 + 2                    => 2+2
f( " ")                  => f(" ")
f("Test \"mystring\" .") => f("Test \"mystring\" .")
f("' ",   " ")           => f("' "," ")

使用我想出的 另一篇文章:\h(?=[^']*(?:'[^']*'[^']*)*$)(?=[^"]*(?:"[^"]*"[^"]*)*$)

它基本上向前看并检查在字符串结尾之前是否有偶数的引号(“”和“”)。

但是,我遇到转义字符和引号内的引号问题。

" ' test "  => The ' causes problem
" \" test " => The \" causes problem

我曾想过使用负面的lookbehinds:(?<!\\)"但无法让它发挥作用。下一个正则表达式失败。当字符串包含转义引号时,它不匹配。

\h(?=[^"]*(?:(?<!\\)"(?:[^"]*?(?<!\\)")[^"]*?)*$)

标签: phpregexpreg-replaceremoving-whitespace

解决方案


您可以使用

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

查看正则表达式演示

细节

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

PHP 演示

$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("' "," ")
)

推荐阅读