如何在PHP中正确地将多个空格替换为单个空格?

6

我在浏览Stack Overflow的答案时发现,大多数人提供的替换多个空格的解决方案是:

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

但是在许多情况下,空格字符包括包含换行、形式进纸、回车、不间断空格等的UTF字符。 这个维基 描述了UTF定义的25个空白字符。

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


为什么要使用正则表达式,当str_replace已经很好用了呢? - Ondřej Hlaváček
3个回答

11

当使用 u 修饰符时,\s 将会变得 Unicode - 感知。因此,一个简单的解决方案是使用

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

查看 PHP 在线演示


是的,它会识别空格,但不会替换像不间断空格这样的空格。我们需要明确指定这些字符。例如,尝试使用此字符串测试您的解决方案:$str = "Hello there".str_repeat(json_decode('"\u00A0"'),10)."Bob!";该字符串有10个由utf代码00A0表示的不间断空格。您可以先尝试echo该字符串以查看其效果。 - Adam Ranganathan
非断空格在我的示例文本中。它*被替换了。这里有一个演示,使用你上面的示例字符串。同时只留下1个空格。 - Wiktor Stribiżew
我根据你的代码尝试了一下,但是没有得到结果。我有什么遗漏吗?$utf = "Hello there".str_repeat(json_decode('"\u00A0"'),10)."Bob!"; $new_str = preg_replace("/\s+/u", " ", $utf); echo $new_str; - Adam Ranganathan
请再次查看http://ideone.com/I8qnpV。您应该检查您的环境是否正确设置为使用UTF工作。 - Wiktor Stribiżew
好奇怪啊。你知道我的环境可能出了什么问题吗?我发布的解决方案在我的当前环境中有效。它可以检测到UTF字符。但是你的解决方案没有给出相同的结果。你有任何想法在哪里可以阅读更多关于这个问题的信息吗? - Adam Ranganathan
有很多原因,请先查看https://dev59.com/OHI-5IYBdhLWcg3w8NSB。 - Wiktor Stribiżew

1

匹配所有Unicode空白字符的模式是[\pZ\pC]。这里有一个单元测试证明它

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

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


1
首先要做的是阅读this有关如何在正则表达式中处理Unicode的解释。具体到PHP,我们需要首先包含PCRE修饰符“u”,以便引擎能够识别UTF字符。所以代码如下:
$pattern = "/<our-pattern-here>/u";

下一步需要注意的是,在PHP中,Unicode字符具有模式\x{00A0},其中00A0不间断空格的十六进制表示。因此,如果我们想用单个空格替换连续的不间断空格,我们可以这样做:
$pattern = "/\x{00A0}+/u";
$new_str = preg_replace($pattern," ",$str);

如果我们要包括维基中提到的其他类型的空格,比如:

  • \x{000D} 回车符
  • \x{000C} 换页符
  • \x{0085} 下一行

我们的模式变为:

$pattern = "/[\x{00A0}\x{000D}\x{000C}\x{0085}]+/u";

但这并不是一个好的方法,因为正则表达式引擎将花费很长时间来查找这些字符的所有组合。这是因为这些字符包含在方括号 [ ] 中,并且我们使用 + 表示一个或多个出现次数。
更好的方法是首先将每个这些字符的所有出现替换为普通空格,然后用单个普通空格替换多个空格。我们移除 [ ]+ 并改用或运算符 | 分隔字符:
$pattern = "/\x{00A0}|\x{000D}|\x{000C}|\x{0085}/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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接