今天碰见一个奇怪的问题,有必要和大家分享一个,是关于
trim
的。
trim
在我们项目中应用场景比较多,所以非常有必要和大家分享一下。我们知道
trim
默认是过滤
* " (ASCII 32 (0x20)), an ordinary space.
* "/t" (ASCII 9 (0x09)), a tab.
* "/n" (ASCII 10 (0x0A)), a new line (line feed).
* "/r" (ASCII 13 (0x0D)), a carriage
return.
* "/0" (ASCII 0 (0x00)), the NUL-byte.
* "/x0B" (ASCII 11 (0x0B)), a vertical tab.
这些字符的,同时我们也可指定过滤字段。我有一个需求需要过滤掉
url
中的
http://
,所以,我使用
$stie = “http://tbtest101.tmail.taobao.net”;
$site = trim($site, “http://”);
但是得到的结果是
btest101.tmail.taobao.ne
注意:
URL
中的最后的
.net
变成
.ne
,导致整个查询失败,然后我尝试使用
$stie = “http://tbtest101.tmail.taobao.cn
”;
$stie = “http://tbtest101.tmail.taobao.com”;
$stie = “http://tbtest101.tmail.taobao.me”;
这些
URL
进行测试,发现他们都能输出正确结果。难道是最后的
t
对整个过滤有影响,然后我把测试条件修改为
$site = “test”;
果不出其然,输出结果是
tes
最后的一个
t
,果真没有了。这不禁让我想起了
trim
默认过滤
/t
,那么会不会以
r,n
结尾的字符,会不会也会过滤掉。
$site=” test n”;
$site=” test t”
输出结果是
;
test
n
test
r
发现
trim
并没有因为查询语句有
”//”
,
trim
过滤出现问题。然后我尝试使用
ltrim
进行测试
$stie = “http://tbtest101.tmail.taobao.net”;
$site = ltrim($site, “http://”);
结果是
btest101.tmail.taobao.net
发现
ltrim
得到的结果是正确的,难道
ltrim
和
trim
的过滤机制不一样,其实查看文档很清楚,
ltrim
只是从字符串的左侧开始
trim
字符而已。至此好像问题,解决了,使用
ltrim
代替
trim
就可以了,至于具体原因,姑且可以认为是
trim
的一个
bug
。
但是,这里面蕴藏着一个巨大的
bug
。在上面的例子中,我定义的
$stie = “http://tbtest101.tmail.taobao.net”;
而过滤后,
$site
对象为
btest101.tmail.taobao.net
其实,仔细看下就会发现
URL
中的
tbtest101
,过滤后为
btest101
,把
t
也过滤了,使用
trim
与
ltrim
的效果都是一样的,只能再仔细看一下文档,
charlist
Optionally, the stripped characters can also be specified
using the charlist
parameter. Simply list all characters that you want
to be stripped. With ..
you can specify a range of characters.
trim
参数的第二项为
string
类型,变量名为
charlist
,仔细看一下文档描述,清楚的知道
trim
是过滤字符的,而不是过滤字符串的。而当我们希望过滤一个字符串中的一部分时,如果我们使用要过滤的字符串为过滤条件,那么这部分字符串肯定会过来掉,但是同时会引起其他怪异行为,这些怪异行为对
trim
来说是完全合法的。打个比方
$test = “this
is trim test, I find one bug, but is not a error”;
如果我们想过滤上面字符串的中的
error
,使用
trim
,可能会这样用
trim($test,”error”);
输出结果是
this is
trim test, I find one bug, but is not a
哈哈,输出正确,其实你了解
trim
的话,你可以这样写
trim($test,”eror”);
当然,也可以这样
trim($test,”eor”);
一样实现与
trim($test,”error”);
相同的效果。看到这里,我们应该大体了解
trim
的原理了。
trim
过滤字符的时候,是以首字符匹配为开始的,直到第一个不满足条件。这句话比较绕,用我一开始的例子说明吧!
$stie =
“http://tbtest101.tmail.taobao.com”;
我的过滤是
$site =
trim($site, “http://”);
过滤后的结果是
btest101.tmail.taobao.ne
之所以把
tbtest101
,过滤成
btest101
的,原因就是
http://
后面跟的是
t
,当然如果后面跟的是
h
和
p
这个字符一样会过滤到。
那么
.net
变成
.ne
的原因又是什么那?
trim
除了上面提到的首字母匹配的规则外,还有一个规则,就是尾匹配过滤,如果
.net
的
t
修改为
h
,
p
字符一样会过滤掉,这就是尾过滤,应该说这种行为不是我们想要的行为,所以
trim
又分为
ltrim,rtrim
,
ltrim
对应的策略就是我提到的第一种规则,字段首字母匹配。
rtrim
对应的策略就是我提到的第二种规则,字段尾匹配。
而
trim
的策略正好是
ltrim+rtrim
的和。至此关于
trim
的所有讨论到此结束。