用 preg_replace 匹配重复的空格

Posted

技术标签:

【中文标题】用 preg_replace 匹配重复的空格【英文标题】:Matching duplicate whitespace with preg_replace 【发布时间】:2011-03-09 09:56:57 【问题描述】:

我正在编写一个 WordPress 插件,其中一个功能是删除重复的空格。

我的代码如下所示:

return preg_replace('/\s\s+/u', ' ', $text, -1, $count);

我不明白为什么我需要u 修饰符。我看过其他插件 使用preg_replace 并且不使用 需要为 Unicode 修改它。一世 相信我有默认安装 WordPress 的。

没有修饰符,代码 用 Unicode 替换所有空格 替换字形而不是空格。

使用 u 修饰符,我不明白 字形,它不会替换所有的空格。

下面的每个空格都有 1-10 个空格。正则表达式仅从每个组中删除空间。

之前:

This sentence  has extra space.  This doesn’t.  Extra  space, Lots          of extra space.

之后:

This sentence has extra space. This doesn’t. Extra space, Lots         of extra space.

$count = 9

如何让正则表达式用一个空格替换整个匹配项?


更新:如果我用普通的 php 试试这个,效果很好
$new_text = preg_replace('/\s\s+/', ' ', $text, -1, $count);

只有当我在 wordpress 插件中使用它时它才会中断。 我在过滤器中使用这个函数:

function jje_test( $text ) 
    $new_text = preg_replace('/\s\s+/', ' ', $text, -1, $count);
    echo "Count: $count";
    return $new_text;


add_filter('the_content', 'jje_test');

我试过了:

删除 the_content 上的所有其他过滤器remove_all_filters('the_content'); 更早或更晚更改添加到 the_content 的过滤器的优先级 \s+, \s\s+, [ ]+等各种排列方式 即使用空字符串替换所有单个空格,也不会替换空格

【问题讨论】:

我已经添加了一个示例,代码和结果在这里:pastebin.com/hm2JMX2w 我用R 代替了空格,这样可以更清楚地知道什么被替换了,什么没有被替换.我正在使用新安装的带有 WordPress 的 LAMP,这似乎已经解决了 unicode 问题。 这里有没有我错过的不使用正则表达式的解决方案? 【参考方案1】:

这将用一个空格替换所有两个或多个空格、制表符和/或换行符的序列:

return preg_replace('/[\pZ\s]2,/u', ' ', $text);

如果$text 保存编码为UTF-8 的文本,则需要/u 标志。即使您的正则表达式中没有 Unicode 字符,PCRE 也必须正确解释 $text

我将\pZ 添加到字符类中,因为PCRE 在使用\s 等速记时仅匹配ASCII 字符,即使在使用/u 时也是如此。添加\pZ 确保所有Unicode 空白都匹配。您的字符串中可能还有其他空格,例如不间断空格。

我不确定在 WordPress 过滤器中使用 echo 是否是个好主意。

【讨论】:

这成功了!谢谢!我想知道它是否是不间断的空格,尽管我没有在 html 源代码中看到它们。我同意使用 echo 它只是为了调试目的来计算匹配的数量。我不明白的是为什么在同一个数据库上运行的所有内置 wordpress 函数(始终默认为 utf-8)不必使用 /u 标志。有关示例,请参见 wp_texturize() 函数:wordpress.taragana.net/wp-includes/… 即使没有/u,仅适用于 ASCII 字符(字节 0 到 127)的正则表达式也可以在 UTF-8 字符串上正常工作,因为 UTF-8 专门设计为对能够理解的进程透明仅 ASCII 并忽略字节 > 127。 根据您对 HTML 源代码的看法,您可能无法“看到”不间断空格,因为它们看起来就像常规空格。 我明白,但是他们的一些函数也匹配空格 \s* 并且似乎在不尝试匹配 Unicode 空格的情况下工作。 在 PCRE 中,\s 仅匹配 ASCII 空格,因此不受 /u 标志的影响。【参考方案2】:

u 修饰符只是将其置于 UTF-8 模式,如果您需要对代码点高于 0x7f 的字符执行任何特定操作,这将非常有用。您仍然可以在不使用该修饰符的情况下处理 UTF-8 编码的字符串,只是无法轻松地专门匹配或转换此类字符。

Unicode 中有一些大于 0x7f 的空白字符。在大多数数据中很少遇到它们。但您可能会看到,例如,不间断空格字符,即 unicode \uA0,或一些稀有字符。

我不知道为什么使用它会导致输出 Unicode“替换”字形。我会说这在其他地方会是一个问题......你输出你的脚本是什么字符编码?

【讨论】:

content-type header设置为charset=UTF-8mysql数据库排序规则设置为utf8_general_ci,wordpress本身的读取设置设置为UTF-8。所以我真的不明白如何以这种方式解释常规空格字符。这不像我有一些奇怪的数据源。我自己输入了数据。 也许你可以在网上的某个地方放一个工作演示 - 有人可能会看到它在做什么并帮助你。 我上面对这个问题的评论有一个链接到一些带有结果的示例代码。【参考方案3】:

为了回答 jjeaton 在 cmets 中对我的第一个回复提出的后续问题,以下内容将每个空格、制表符和/或换行符序列替换为该序列中的第一个字符。实际上,这会删除两个或多个空白字符的每个序列中的第二个和后续空白字符。空格替换为单个空格,制表符替换为单个制表符,等等。空格和制表符(按此顺序)替换为空格,制表符和制表符替换空格替换为制表符等。

return preg_replace('/([\pZ\s])[\pZ\s]+/u', '$1', $text);

此正则表达式首先匹配一个空格并使用捕获组捕获它,然后是一个或多个空格。替换文本只是重新插入与第一个(也是唯一一个)捕获组匹配的文本。

【讨论】:

【参考方案4】:

不知道有什么修饰符,但这确实成功了:

<?php
$text = ' Hi,   my name is    Andrés.  ';
echo preg_replace(array('/^\s+/', '/\s+$/', '/\s2,/'), ' ', $text);
/*
Hi, my name is Andrés.
*/
?>

【讨论】:

不幸的是,仍然对我不起作用。我也尝试使用/\s2,/,但它对我来说不匹配任何东西。也许我的 wordpress/php 设置有问题? 你从哪里得到你的文本? 让我更具体一点:你应该让 php 知道你正在从数据库发送和检索“什么”。在任何连接之后和任何查询之前,您应该声明 msyql_set_charset('utf8', $connection_resource);【参考方案5】:
preg_replace('!\s+!', ' ', 'This sentence  has extra space.  This doesn’t.  Extra  space, Lots          of extra space.');

【讨论】:

以上是关于用 preg_replace 匹配重复的空格的主要内容,如果未能解决你的问题,请参考以下文章

preg_replace/string_replace 符号 - 或 * 到空格

即使未检测到,如何在php中删除空格[重复]

如何在 PHP 中替换字符串中一个数字加上一个带逗号的空格的所有匹配项

如何替换所选用户名中的空格? [复制]

PHP preg_replace() 正则替换所有符合条件的字符串

php 中文标点逗号‘,’怎么用正则匹配