从字符串中删除ASCII字符"194"的空格

19

最近遇到一个非常奇怪的问题,我的数据库中包含了一些看起来像是普通空格字符的字符串,但实际上它们是其他东西。

例如,对该字符串应用trim()函数:

"TEST "

让我感到:

"TEST "

结果是,所以我复制并粘贴字符串中的最后一个字符:

echo ord(' ');
194

194?根据ASCII表格应该是。所以我现在很困惑。为什么这个字符看起来像空格,当使用trim()失败时,如何trim()这样的字符呢?

7个回答

27

很有可能是由两个字节组成的194160序列,它是一个NO-BREAK SPACE码点的UTF-8编码(在HTML中等同于 实体)。

尽管看起来像空格,但它实际上不是空格。(例如,你会发现它不换行。)使用正则表达式匹配\s可以匹配它,但与空格进行简单比较、或使用trim()都无法删除它。

要用正常空格替换NO-BREAK spaces,你可以尝试以下做法:

$string = str_replace("\u{c2a0}", " ", $string);
或者
$string = str_replace("\u{c2a0}", "", $string);

去除它们


谢谢您提供更详细的答案,但不幸的是对我没有用。值得一提的是,我已经安装了lib_mysqludf_preg,并且能够通过以下方式修复我的表格:UPDATE table SET cell = trim(preg_replace('/[[:space:]]+/',' ',cell)); - But those new buttons though..
感谢马克的澄清,但是不,正则表达式\s是*不匹配的。请看我的答案以获取可行的替代方案。 - Codesmith
点赞了,你的解释100%正确,只需执行以下操作来证明:$string = html_entity_decode(" "); print ORD($string[0]); 输出:194。 但是!你的解决方案无效。Codesmith的答案确实有效,我仍然会为你的解释点赞。 - HoldOffHunger
哇,这刚解决了我数据库中的一个谜团!我有一些带有空格的输入,但是我找不到匹配项,结果发现一些用户将字符194输入为空格。他们怎么可能这样做呢?从他们的笔记本电脑上他们可以选择UTF-8或其他编码吗? - Rosemary

14

您可以尝试使用:

PHP的trim函数

$foo = "TEST ";
$foo = trim($foo);

PHP str_replace

$foo = "TEST ";
$foo = str_replace(chr(194), '', $foo);

重要提示:你可以尝试使用chr(194).chr(160)或者'\u00A0'

PHP preg_replace

$foo = "TEST ";
$foo = preg_replace('#(^\s+|\s+$)#', '', $foo);

OR(我不确定它是否能很好地运行)

$foo = "TEST ";
$foo = preg_replace('#[\xC2\xA0]#', '', $foo);

6
谢谢。唯一有效的是 chr(194).chr(160)。这到底是什么? - But those new buttons though..
2
PHP的chr()函数返回ASCII码数字对应的字符。您可以查看ASCII表。如果您想获取一个字符的ASCII码,可以使用ord()函数。 - Condorcho
1
这个对我有用:$link = preg_replace('/[\\\u25A0\\\u00A0\s]+$/u', '', $value); - NineCattoRules
@NineCattoRules,也许你可以创建一个答案来更详细地解释一下它的评论:D - Jorge Olaf

5

我遇到了同样的问题。通过以下方法解决:

trim($str, ' ' . chr(194) . chr(160))

3

您可能是从Excel / CSV中获取了原始数据。我正在将其导入到我的mysql数据库中,花费了几个小时才弄清楚为什么它会出现填充的情况,并且修剪似乎无法正常工作(必须检查每个CSV列字符串中的每个字符),但实际上它看起来像所有空格位于末尾。事实上,Excel似乎添加chr(32) + chr(194) + chr(160)以“填充”该列。这是对我有效的方法,以便拥有漂亮而完美的字符串用于加载到数据库中:

  // convert to utf8
  $value = iconv("ISO-8859-15", "UTF-8",$data[$c]);
  // excel adds 194+160 to fill up!
  $value = rtrim($value,chr(32).chr(194).chr(160));
  // sanitize (escape etc)
  $value = $dbc->sanitize($value);

2

我需要在PHP中截取字符串,但得到的结果都相同。

在发现Mark Bakers的回答后,我使用以下方法代替了trim

// $str = trim($str); // won't strip UTF-8 encoded nonbreaking spaces
$str = preg_replace('/^(\\s|\\xC2\\xA0)+|(\\s|\\xC2\\xA0)+$/', '', $str);

2
php -r 'print_r(json_encode(" "));'
"\u00a0"
$string = str_replace("\u{00a0}", "", $string); //not \u{c2a0}

很好的发现,当@Mark Baker发布时,我在想为什么它不起作用。不过你应该加入更多的解释,而不仅仅是代码答案。 - But those new buttons though..
"194, 160" 是十进制,"c2a0" 是十六进制,它们本质上是相同的。我们需要在 "\u" 后面获得 Unicode 代码点,而 "c2a0" 不是 Unicode 代码点。我们可以使用 json_encode 获得 Unicode 代码点,然后我们得到 "\u00a0"。您可以在 https://www.utf8-chartable.de/ 获取更多信息。 - Awesome

0

我认为我应该贡献自己的答案,因为现在我已经清楚了发生了什么。问题源于处理包含非断空格实体 的html。一旦您在php的DOMDocument()中加载内容,所有实体都会转换为其解码值,并在解析时得到一个非断空格字符。无论如何,在不同的情况下,以下方法是将它们转换为常规空格的另一种选择:

$foo = str_replace(' ',' ',htmlentities($foo));

这个方法首先将非断空格转换为其HTML实体,然后再转换为普通空格。现在可以像平常一样轻松地修剪$foo的内容。


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