PHP中文文字处理技巧 字符串逐字分割 中文字符串 组合字符串 explode

我们都知道,在PHP中处理字符串,可以用substr,str_split等等众多的方法,但是我想每个人都遇到过一个问题,那就是如何完美的处理中文字符串!我们知道,中文与英文和数字完全不同,英文和数字通常情况下都仅仅是占用一个字节,但是中文在不同编码下占用的字节是不同的,在UTF8中占用3个字节,而在GBK中则占用2字节。

一、字符串逐字分割

即使我们确定使用的编码格式,例如我们最常用的UTF8编码,知道汉字是占用3字节,那么对于中英文混排,依然会比较头疼,因为substr,str_split等方法都是依照字节分割的,例如我们想要逐字分割字符串,或是以一定长度分割字符串,这个问题就会变得复杂,如果我们以3为倍数分割,除非我们保证字符串是纯粹的中文,否则结果依然有很大几率将中文“切碎”,当然如果你去网上搜索,可能会有人告诉你,可以用mb_substr(),但是你不得不注意一点,mb并不是PHP本身预装的,可能有些集成环境带有这个,但同样的,也有很多PHP不会带有这些mb开头的方法。例如我的服务器就没有mb开头的这些方法。

而在网上你能找到的还有利用循环遍历的方法去判断字符的编码,以及是否是汉字,然后再逐个用substr分割,虽然这个方法可以不借助mb这类额外的东西,但是实现起来实在过于麻烦,实际上只要你用的PHP不是太旧,我们只需要一步就能轻松的做到字符串的逐字分割。

我们需要借助的是一种对于字符串处理十分擅长,但很多人认为是比较高级的东西——正则表达式。可能有些人提到正则表达式,会比较反感,其实我个人最开始也感觉正则表达式比较复杂,因为里面用了各种“标点符号”来标记各种功能。但当你发现它的强大之后,你真的会爱上它。

我们只需要使用preg_match_all("/./u",$str,$arr);就可以得到一个名为$arr的字符数组,也就是我们需要的逐字分割的结果。没错,仅仅是这样简短的一行代码,就达到了逐字分割字符串的目的,是不是很简单呢?其实原理也很简单。

我们首先说一下preg_match和preg_match_all这两个方法,这两个方法是PHP内置的,专门用来匹配正则的方法,所以不用担心你的PHP环境不支持它们。preg_match是仅匹配一次,我们通常用来提取某一个字符串中的一个内容,当它找到第一个符合的结果时,便会直接将结果返回给变量,并且停止匹配,而preg_match_all则是匹配所有符合的结果,他会将你传给他的字符串反复匹配,找到所有匹配的结果。

然后就是我们使用的正则表达式,“/./u”十分的简单,正则表达式以斜线开始和结束,而在结束的斜线后面则可以设置属性,常用的有i,u,g等,这里我们使用的u十分的重要,因为这里的u代表将字符串以UTF8编码格式来处理,如果没有这个,我们就不能正常的处理中文字符。而“.”则是代表任意字符,因此这里我们只是匹配一个UTF8的字符,而因为我们使用了preg_match_all所以我们就可以得到所有的单个字符,也就达到了逐字分割的目的。

二、中文字符串长度

在获取中文字符串长度的时候,也会遇到问题,我们使用str_len获取的字符串长度也是不正常的,那么想要获取含有中文的字符串的字符个数该怎么办呢?其实非常的简单,我们依然使用preg_match_all("/./u",$str,$arr);就可以了,只不过我们要拿到的不是$arr,而是preg_match_all的返回值,也就是$len=preg_match_all("/./u",$str,$arr);我们拿到的$len就是字符串的长度,这也是我为什么建议使用preg_match_all逐字分割字符串,而不是用preg_split,因为我们用preg_match_all可以一步同时获取数组和字符串长度。

需要注意的是,还有一些文章中使用了explode("",$str);来逐字分割字符串,但是这种做法是不正确的,explode的第一个参数不可以为空!

三、以字符串分割或组合字符串

接下来我们简单了解一下其他两个最常用的方法,他们可以说是一对好兄弟,那就是explode和implode,长的都很像,但是功能却刚好是相反的。在我们处理一些字符串的时候,很经常用到这两个方法。

explode是用来以字符串分割字符串的方法,我们得到的是一个数组,并且这个数组不包含分隔符,例如我们有一个字符串是 “15912345678/18899995464”两个电话号,我们想要将其分开,怎么办呢?只需要用explode("/","15912345678/18899995464");就可以得到一个Array([0]=>"15912345678",[1]=>"18899995464")的数组,这种情况我们一般用于多个结果,例如多个电话,多个姓名等,我们使用explode分割后就可以遍历处理。

implode的作用刚好相反,是以字符串为分隔符将数组组合成一个字符串,例如我们要将一个数组的数据用逗号分割,implode(",",$arr);我们得到的就是“1,2,3,4”这样的字符串。

我们在部分时候,处理一些数量不确定的数据的时候,往往会将这些内容作为一个字符串保存在数据库的一个字段中,而我们使用的时候就需要用explode分割开进行处理。例如个人资料,我们在填写的时候,往往允许添加多个工作经历,多个就读学校,这些数据的条目数量不确定,我们可能就会将其作为一个字符串写入到一个字段中。

在大部分语言中都存在这样的方法,但是PHP的自由度更高一些,并不仅限于一个字符,你也可以使用字符串来分割或组合,例如implode("/!/",$arr);这种方式也是可以的,这样其实十分有用,例如我们写入SQL插入语句的VALUES的时候,我们知道,SQL插入语句的VALUES要求是('val1','val2','val3'……)这样的格式,每一个值都要求使用单引号括起来,那么我们如果要每一个值使用一个变量,逐个去写,显然比较麻烦,那么我们有没有比较“偷懒”的方式呢?当然有!

首先,你的表单顺序和你插入的字段顺序要一致,其次所有不需要写入数据库的控件不要给name属性。这样就可以保证一点,$_POST数组得到的是刚好对应数据库字段的数据。接下来我们只要,$values="'".implode("','",$_POST)."'";就可以得到一个格式为'val1','val2',…… 这样的字符串,最后只需要在VALUES的地方写到 VELUES ($values)就可以一步完成插入的操作了。为了防止看不清上面那行代码,我用文字叙述一下吧,首先我们放两个字符串,里面是单引号,即 双引号 单引号 双引号 这是开头和结尾两个字符串的部分,不要看成五个单引号。中间的部分则是拼接字符串,间隔符是 单引号 逗号 单引号 这个部分,而我们同样需要把单引号括在双引号里面。为什么前后还要加一个单引号呢?因为implode的间隔符是加在值中间的,只用implode得到的刚好是 val1','val2','val3 因为 ',' 是作为分割符,所以只在中间,因此第一个值前面,和最后一个值后面都会缺少一个单引号,所以我们需要加上。

字符串的逐字分割我们经常会用到,尤其是当你去制作模糊搜索的时候,这一点就显得十分必要,但当你去通过百度或是Google查找的时候,我发现很少有提到这种方法的,你学会了嘛?PHP正则的应用之后会继续讲到。





评论

草丛撸管禁止插眼:一直零零碎碎的看一些这方面的资料,都似懂非懂。这下全给整明白了。感谢!!!
06月25日 10:30
李佳音:期待你的更新
06月25日 10:35
老子是个弱女子:好文要多读几遍,并实践
06月25日 10:38
小黑:通俗易懂 贊
06月25日 10:52
一畔紫湖:好文章,难得的好。
06月25日 10:56
北落师门:楼主功底不错,写得很好
06月25日 11:12
窗帘:楼主我帮你点赞 楼主请继续
06月25日 12:45
二十几岁:好文,期待后续~~~
06月25日 14:39
06月25日 19:44
这个手刹不太灵:之前也看过不少有关此类的文章,但还是很迷糊。LZ的文章写得真好,对于吾等理解能力缺陷的程序员来说,就喜欢这类通俗易懂的文章,哈哈。
06月25日 20:58

赞助商

12321