如何在 PHP 中用单个空格正确替换多个空格?

Posted

技术标签:

【中文标题】如何在 PHP 中用单个空格正确替换多个空格?【英文标题】:How to correctly replace multiple white spaces with a single white space in PHP? 【发布时间】:2017-03-08 22:46:19 【问题描述】:

我浏览了 SO 的答案,发现最适合替换多个空格的解决方案是:

$new_str = preg_replace("/\s+/", " ", $str);

但在许多情况下,空白字符包括 UTF 字符,包括换行、换页、回车、不间断空格等。This wiki 描述 UTF 定义了 25 个字符定义为空白。

那么我们如何使用正则表达式替换所有这些字符呢?

【问题讨论】:

为什么 regexp,当 str_replace 工作得很好? 【参考方案1】:

当传递 u 修饰符时,\s 变为可识别 Unicode。因此,一个简单的解决方案是使用

$new_str = preg_replace("/\s+/u", " ", $str);
                             ^^

请参阅php online demo。

【讨论】:

是的,它会意识到,但它不会像不间断空格那样替换空格。我们需要专门指定这些字符。例如,使用以下字符串尝试您的解决方案:$str = "Hello there".str_repeat(json_decode('"\u00A0"'),10)."Bob!"; 该字符串有 10 个不间断的空格,由 utf 代码 00A0 表示。您可以先尝试回显该字符串以查看其作用。 我的示例文本中有不间断的空格。它替换了。这是a demo,上面有您的示例字符串。里面也只剩下 1 个空间。 我根据你的代码尝试了这段代码,但我没有得到结果。我错过了什么吗? $utf = "Hello there".str_repeat(json_decode('"\u00A0"'),10)."Bob!"; $new_str = preg_replace("/\s+/u", " ", $utf); echo $new_str; 再次,请参阅ideone.com/I8qnpV。您应该检查您的环境是否设置为正确使用 UTF。 好吧,这很奇怪。你知道我的环境可能有什么问题吗?我发布的解决方案适用于我目前的环境。它检测 UTF 字符。但是您的解决方案并没有给出相同的结果。知道我可以在哪里阅读更多相关信息吗?【参考方案2】:

匹配all Unicode whitespaces 的模式是[\pZ\pC]。这是unit test to prove it。

如果您在 UTF-8 中解析用户输入并需要对其进行规范化,那么将匹配基于该列表非常重要。所以回答你的问题是:

$new_str = preg_replace("/[\pZ\pC]+/u", " ", $str);

【讨论】:

【参考方案3】:

首先要做的是阅读this解释如何在正则表达式中处理unicode。专门针对 PHP,我们首先需要包含 PCRE 修饰符“u”,以便引擎识别 UTF 字符。所以这将是:

$pattern = "/<our-pattern-here>/u";

接下来要注意的是,在 PHP 中,unicode 字符具有\x00A0 模式,其中00A0non-breaking space 的十六进制表示。因此,如果我们想用一个空格替换连续的不间断空格,我们将有:

$pattern = "/\x00A0+/u";
$new_str = preg_replace($pattern," ",$str);

如果我们要包括 wiki 中提到的其他类型的空间,例如:

\x000D回车 \x000C换页 \x0085下一行

我们的模式变成:

$pattern = "/[\x00A0\x000D\x000C\x0085]+/u";

但这真的不是很好,因为正则表达式引擎将花费很长时间来找出这些字符的所有组合。这是因为字符包含在方括号 [ ] 中,并且我们有一个 + 表示出现一次或多次。

获得更快结果的更好方法是首先将所有这些字符的所有出现替换为普通空格。然后用一个普通空格替换多个空格。我们删除 [ ]+ 并使用 or 运算符 | 分隔字符:

$pattern = "/\x00A0|\x000D|\x000C|\x0085/u";
$new_str = preg_replace($pattern," ",$str); // we have one-to-one replacement of character by a normal space, so 5 unicode chars give 5 normal spaces
$final_str = preg_replace("/\s+/", " ", $new_str); // multiple normal spaces now become single normal space

【讨论】:

以上是关于如何在 PHP 中用单个空格正确替换多个空格?的主要内容,如果未能解决你的问题,请参考以下文章

在Python中用单个空格替换多个空格[重复]

如何在 PHP 中的变量中用空格替换制表符?

如何在PHP中用正则表达式替换所有实际上不是空格的空格

在 PHP 中用一个空格替换多个空格和换行符

正则表达式或用单个空格替换多个空格的方法

删除Javascript中的所有多个空格并替换为单个空格[重复]