如何替换解码的不间断空格(nbsp)

46
假设我有一个字符串是"a s d d"htmlentities将其转换为"a s d d"。如何使用preg_replace替换它而不编码为实体?我尝试了preg_replace('/[\xa0]/', '', $string);,但没起作用。我试图从我的字符串中删除那些特殊字符,因为我不需要它们。除了正则表达式之外还有哪些可能性?
要编辑的字符串:http://pastebin.com/raw/7eNT9sZr,使用函数preg_replace('/[\r\n]+/', "[##]", $text),以便稍后使用implode("</p><p>", explode("[##]", $text))
我的问题不完全是“如何”做到这一点(因为我可以对实体进行编码、删除我不需要的实体并解码实体)。而是如何只用str_replace或preg_replace删除那些实体。

htmlentities 是防止 XSS 攻击的一种方法。如果您想在浏览器中呈现,那么 &nbsp 将被解析为空格。否则,该函数就没有用处。 - georoot
2
你想要替换空格还是 &nbsp; - Joshua
@georoot,“ ”和“ ”在HTML中的信息是不同的。一个是空格,一个是不间断空格。只有不间断空格被编码为“ ”,而不是普通空格。 - user2864740
@Grzegorz 使用SQL参数化查询来进行“存储到数据库”的操作。无论如何,输入数据已经包含一个非正常空格。 - user2864740
2
我认为他正在寻找一种方法来从字符串中删除不间断空格,而无需先将它们转换为HTML实体。 - simon
显示剩余9条评论
4个回答

95

问题说明

你的代码无法正常工作的原因是你没有正确指定不间断空格符

在UTF-8编码中,不间断空格符的正确代码是0xC2A0,它由两个字节组成-0xC2 (194)和0xA0 (160),因此从技术上讲,您只指定了字符代码的一半。

一点理论知识

早期的字符编码使用固定数量的位来编码其集合中的每个字符。例如,最初的ASCII编码每个字符使用7位,扩展ASCII使用8位。

UTF-8编码是所谓的可变宽度字符编码,这意味着用于表示单个字符的位数是可变的,在UTF-8的情况下,字符代码由一个到四个(8位)字节(八位字节)组成。通常类似于Huffman编码,更频繁使用的字符具有较短的代码,而更罕见的字符具有较长的代码。这有助于减少平均文本的数据大小。

解决方案

您可以使用简单(快速)的str_replace或使用更灵活的正则表达式来替换文本中所有出现的UTF-8不间断空格符,具体取决于您的需求:

// faster solution
$regular_spaces = str_replace("\xc2\xa0", ' ', $original_string);

// more flexible solution
$regular_spaces = preg_replace('/\xc2\xa0/', ' ', $original_string);

注意事项

请注意,在使用str_replace()函数时,必须要用双引号(")来包含搜索字符串。因为该函数不能识别字符代码的文本表示形式,所以需要将这些代码转换为实际字符。PHP会自动完成这个步骤,因为用双引号括起来的字符串会被处理,特殊序列 (例如换行符\n、字符代码的文本表示,等等)会被替换为实际字符 (例如UTF-8中\n0x0A),然后才使用该字符串值。

相比之下,preg_replace()函数可以识别字符代码的文本表示形式,因此在这种情况下,您可以使用撇号 (单引号,') 来包含搜索字符串


2
请注意,str_replace() 也可以使用,而且速度更快。 - simon
1
@simon 谢谢,你说得对。已添加到我的答案中。 - David Ferenczy Rogožan
2
我完全不知道我需要写\xc2\xa0,结果写成了\xc2a0... 我失败了。谢谢! - Grzegorz
1
也许你能告诉我如何在组内替换它?preg_replace('/[\x0E-\x1f]/', '', $string); - Grzegorz
1
@Grzegorz,我不确定你的意思是什么。你是指如何表达方括号中的代码([\xc2\xa0])是一个单一字符而不是两个字符吗? - David Ferenczy Rogožan
显示剩余5条评论

23

4
这绝对是最佳选择,应该被选为答案。 - Moritz Friedrich
2
对我有效的唯一答案! - user3382203
1
这个解决方案也是最灵活的 - 我需要 trim() 一个字符串,但不间断的空格没有被移除,所以我不是先替换再修剪,而是使用了一个简单的 preg_replace("/^\s+|\s+$/u", "", $str) - Francesco Marchetti-Stasi
据我所见,这将把所有连续的空格替换为一个。你可能需要在\s后面移除+以保持空格数量不变。另外,我不确定,但这可能也会删除换行符。 - Taha Paksu

0
只需要 preg_replace('/\s/', ' ',$string) 就能完美地运行。

0

选择正确的字符集

来处理你的字符串。
$yourCharset='UTF-8'; // or 'ISO8859-1', or...

使用 html_entity_decode 的返回值进行替换。
$string=str_replace(html_entity_decode('&nbsp;',ENT_COMPAT,$yourCharset),' ',$string);

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