今天碰见一个奇怪的问题,有必要和大家分享一个,是关于 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 的所有讨论到此结束。