php -> preg_replace -> 仅在引号之间删除 space

php -> preg_replace -> remove space ONLY between quotes

我试图删除 space ONLY between quotes like:

$text = 'good with spaces "here all spaces should be removed" and here also good';

有人可以帮忙编写一段有效的代码吗?我已经试过了:

$regex = '/(\".+?\")|\s/';

$regex = '/"(?!.?\s+.?)/';

没有成功,我发现了一个方向错误的样本:-( Removing whitespace-characters, except inside quotation marks in PHP?但我无法更改它。

谢谢新

查看以下代码片段:

<?php
$text = 'good with spaces "here all spaces should be removed" and here also good';
echo "$text \n";
$regex = '/(\".+?\")|\s/';
$regex = '/"(?!.?\s+.?)/';
$text = preg_replace($regex,'', $text);
echo "$text \n";
?>

我发现 a sample that works 方向错误:-(


@Graham:正确

$text = 'good with spaces "here all spaces should be removed" and here also good'
should be 
$text = 'good with spaces "hereallspacesshouldberemoved" and here also good';

这种问题用preg_replace_callback就可以轻松解决。这个想法包括提取引号之间的子字符串,然后在回调函数中编辑它:

$text = preg_replace_callback('~"[^"]*"~', function ($m) {
    return preg_replace('~\s~', '#', $m[0]);
}, $text);

这是最简单的方法。


preg_replace 的单一模式来完成它更复杂,但它是可能的:

$text = preg_replace('~(?:\G(?!\A)|")[^"\s]*\K(?:\s|"(*SKIP)(*F))~', '#', $text);

demo

图案详情:

(?:
    \G (?!\A)  # match the next position after the last successful match
  |
    "          # or the opening double quote
)
[^"\s]*        # characters that aren't double quotes or a whitespaces
\K             # discard all characters matched before from the match result
(?:
    \s         # a whitespace
  |
    "           # or the closing quote
    (*SKIP)(*F) # force the pattern to fail and to skip the quote position
                # (this way, the closing quote isn't seen as an opening quote
                # in the second branch.)
)

这种方式使用 \G 锚点来确保所有匹配的空格都在引号之间。

边缘情况:

  • 有一个孤立的开头引号:在这种情况下,从最后一个引号到字符串末尾的所有空格都被替换。但是,如果您愿意,可以更改此行为,添加前瞻性检查是否存在收盘价:

    ~(?:\G(?!\A)|"(?=[^"]*"))[^"\s]*\K(?:\s|"(*SKIP)(*F))~

  • 双引号可以包含必须忽略的转义双引号:您必须像这样描述转义字符:

    ~(?:\G(?!\A)|")[^"\s\\]*+(?:\\\S[^"\s\\]*)*+(?:\\?\K\s|"(*SKIP)(*F))~


@revo 建议的其他策略:使用前瞻检查某个位置的剩余报价数量是奇数还是偶数:

\s(?=[^"]*+(?:"[^"]*"[^"]*)*+")

这是一个短模式,但对于长字符串可能会出现问题,因为对于每个带有空格的位置,您必须检查字符串直到最后一个引号。