PHP使用preg_replace:移除水平空白但保留引号内含转义引号的空白
解决PHP中移除引号外水平空白但保留引号内空白的问题
要实现移除所有引号外的水平空白,同时保留单/双引号(包括转义引号)内的空白,关键是要准确区分“真正的引号边界”和“被转义的引号”,以及正确跳过引号内的内容。你之前的正则因为没有处理转义字符的场景,导致在遇到转义引号或引号嵌套时失效,我来给你一个可靠的解决方案:
最终实现代码
function removeOutsideWhitespace($input) { // 正则核心:匹配引号内的内容并跳过,只替换外部的水平空白 $pattern = '/(?:(["\'])(?:\\.|(?!\1)[^\\])*\1)(*SKIP)(*FAIL)|\h/'; return preg_replace($pattern, '', $input); } // 测试你的示例 echo removeOutsideWhitespace('2 + 2') . PHP_EOL; // 输出:2+2 echo removeOutsideWhitespace('f( " ")') . PHP_EOL; // 输出:f(" ") echo removeOutsideWhitespace('f("Test \"mystring\" .")') . PHP_EOL; // 输出:f("Test \"mystring\" .") echo removeOutsideWhitespace('f("\' ", " ")') . PHP_EOL; // 输出:f("\' "," ") // 测试之前失效的场景 echo removeOutsideWhitespace('" \' test "') . PHP_EOL; // 输出:" ' test "(内部空格保留) echo removeOutsideWhitespace('" \" test "') . PHP_EOL; // 输出:" \" test "(内部空格保留)
正则表达式详解
让我们拆解一下这个正则的逻辑:
(?:(["\'])(?:\\.|(?!\1)[^\\])*\1):匹配完整的引号包裹内容(["\']):捕获当前匹配的引号(单引号或双引号)到分组1(?:\\.|(?!\1)[^\\])*:匹配引号内的所有内容:\\.:匹配任意转义字符(包括转义引号,比如\"或\')(?!\1)[^\\]:匹配不是转义符、也不是当前分组1引号的普通字符
\1:匹配和分组1一致的闭合引号,确保引号成对
(*SKIP)(*FAIL):这是正则的“跳过匹配”技巧,告诉引擎:匹配到的这部分内容(引号内的部分)不需要处理,直接跳过|\h:匹配所有未被跳过的水平空白字符,最终被替换为空字符串
这个方案完美解决了你之前遇到的问题:无论是转义引号、引号内嵌套其他引号,都能准确识别并保留内部的空白,只清理引号外的水平空白。
内容的提问来源于stack exchange,提问作者T. Doe
相关产品推荐
相关产品推荐

