显然,mb_*
family中没有mb_trim
,所以我尝试为自己实现一个。
我最近在php.net的评论中发现了这个正则表达式:
/(^\s+)|(\s+$)/u
因此,我将通过以下方式实现它:
function multibyte_trim($str)
{
if (!function_exists("mb_trim") || !extension_loaded("mbstring")) {
return preg_replace("/(^\s+)|(\s+$)/u", "", $str);
} else {
return mb_trim($str);
}
}
正则表达式对我来说似乎是正确的,但我对正则表达式一窍不通。这会有效地删除字符串开头/结尾的任何Unicode空格吗?
8条答案
按热度按时间wgmfuz8q1#
标准的
trim
函数删除了一些空格和类空格字符,这些字符被定义为ASCII字符,表示从0
到0100 0000
的特定 * 字节 *。ProperUTF-8输入永远不会包含由字节
0xxx xxxx
组成的多字节字符。properUTF-8多字节字符中的所有字节都以1xxx xxxx
开头。这意味着在一个properUTF-8序列中,字节
0xxx xxxx
只能引用单字节字符,因此PHP的trim
函数永远不会删除“半个字符”假设你有一个properUTF-8序列(要非常非常小心unproperUTF-8序列)。ASCII正则表达式中的
\s
大多数匹配与trim
相同的字符。带有
/u
修饰符的preg
函数只适用于 *UTF-8编码的正则表达式 *,并且/\s/u
也匹配UTF8的nbsp。这种不间断空格的行为是使用它的唯一优点。如果要替换其他非ASCII兼容编码中的空格字符,则两种方法都不起作用。
换句话说,如果你想删除ASCII兼容字符串中的空格,就使用
trim
。使用/\s/u
时,要注意文本中nbsp的含义。请注意:
x6yk4ghg2#
我不知道你想用你定义的无限递归函数做什么,但是如果你只是想要一个多字节安全的修剪,这将是工作的。
xvw2m8pv3#
本版本支持第二个可选参数$charlist:
但不支持范围使用“..”。
a9wyjsp74#
好了,我采用了@edson-medina的解决方案,修正了一个bug,并添加了一些单元测试。下面是我们用来给予mb提供trim,rtrim和ltrim对应项的3个函数。
以下是我为感兴趣的人编写的单元测试:
lc8prwob5#
您还可以使用
preg_replace('/^\p{Z}+|\p{Z}+$/u','',$str);
修剪UTF-8字符串上的非ascii兼容空格(例如,不间断空格\s
将仅匹配“ascii兼容”空格字符**,即使具有u
修饰符**。但是
\p{Z}
将匹配所有已知的Unicode空格字符gmxoilav6#
mb_ereg_replace似乎可以解决这个问题:
..但是我对正则表达式的了解不够,不知道如何添加“charlist”参数,人们期望它能够提供给trim()--即要修剪的字符列表--所以我只是将正则表达式作为一个参数。
您可能有一个特殊字符数组,然后在构建正则表达式字符串时,针对charlist中的每个字符逐个执行该数组,并相应地对它们进行转义。
wf82jlnq7#
(移植自
trim
上的一个重复的Q,与NBSP有冲突。)以下注解从PHP 7.2+起有效。里程可能与早期版本不同(请在评论中报告)。PHP
trim
忽略未中断的空格。它只删除基本ASCII范围内的空格。作为参考,the source code的trim如下所示(即没有未记录的trim特性):其中,除了普通的空格(ASCII 32,``)之外,这些都是ASCII控制字符;低频(10:
\n
)、全周波(13:\r
)、高温(9:\t
)、VT(11:\v
)、空值(0:\0
).(注意,在PHP中,转义字符必须用双引号括起来:"\n", "\t"
等。否则,它们将被解析为文字\n
等。)以下是使用
preg_replace
的三种风格trim
(ltrim
、rtrim
、trim
)的简单实现,这些实现使用Unicode字符串:您可以将它们 Package 到自己的
mb_*trim
函数中。根据PCRE specification,
u
Unicode模式打开时的\s
“任意空格”转义序列字符将匹配以下所有空格字符:您可以看到
preg_replace
的test iteration,其中u
Unicode标志处理了列出的所有空格。它们都按照PCRE规范进行了修剪。如果您只针对上面的水平空格,\h
将匹配它们,就像\v
匹配所有垂直空格一样。在一些答案中看到的
\p{Z}
的使用在某些情况下会失败;特别是,大部分的ASCII空间,令人震惊的是,蒙古语元音分隔符也是如此。忽必烈汗会大发雷霆的。下面是\p{Z}
的错误列表:U+0009 * 水平制表符(HT)、U+000 A * 换行符(LF)、U+000 C * 换页符(FF)、U+000 D * 回车符(CR)、U+0085 * 下一行(NEL)* 和U+180 E * 蒙古文元音分隔符。*至于为什么会发生这种情况,上述PCRE规范还指出:“*
\s
与\p{Z}
或\h
或\v
匹配的任何字符 *"。也就是说,\s
是\p{Z}
的超集。然后,只需使用\s
代替\p{Z}
。这样更全面,对于阅读您代码的人来说,导入也更直观。他们可能不记得所有字符类型的短字符。bfhwhh0e8#
∮ ∮我的两分钱∮
你的问题的实际解决方案是,在修改外来输入字符串之前,你应该先做编码检查。许多人很快就学会了"净化和验证"输入数据,但在早期学习识别字符串的基本性质(字符编码)的步骤时却很慢。
用多少字节来表示每个字符?如果UTF-8格式正确,它可以是1(
trim
处理的字符)、2、3或4字节。当遗留的或格式不正确的UTF-8表示开始起作用时,问题就出现了--字节字符边界可能不像预期的那样对齐(外行话)。在PHP中,有些人主张所有字符串都应该强制符合正确的UTF-8编码(每个字符1、2、3或4个字节),其中
trim()
之类的函数仍然有效,因为它处理的字符的字节/字符边界与trim()
试图从字符串的开头和结尾消除的扩展ASCII/1字节值是一致的(trim manual page)。然而,因为计算机编程是一个多样化的领域,一个人不可能有一个一刀切的方法,在所有的情况下工作。也就是说,写你的应用程序的方式,它需要正常工作。只是做一个基本的数据库驱动的网站与表单输入?* 是 *,为我的钱迫使一切都是UTF-8。
trim
函数可以删除默认字符或用户指定的字符。2这一点很重要,尤其是当你需要你的trim
来处理一些中文字符时。我更愿意处理别人无法访问我的网站的问题,然后是不应该发生的访问和响应问题。当你考虑它时,这符合 * 最小特权 *(安全性)和 * 通用设计 *(可访问性)的原则。
总结
如果输入数据不符合正确的UTF-8编码,您可能需要throw an exception。您可以尝试使用PHP multi-byte functions来确定您的编码,或者使用其他一些多字节库。如果PHP编写为完全支持unicode,以及何时编写(Perl、Java ...),PHP将因此变得更好。PHP unicode的努力在几年前就夭折了,因此,您不得不使用额外的库来理智地处理UTF-8多字节字符串,仅仅将
/u
标志添加到preg_replace()
中并不是着眼于全局。更新:
话虽如此,我相信下面的多字节修剪对于那些试图从url的路径组件中提取REST资源的人来说会很有用(当然,查询字符串更少。这在净化和验证路径字符串之后将是有用的。