php实现过滤中英文标点符号[gbk编码环境]
因項(xiàng)目需求需要對帖子標(biāo)題做去重判斷,前提是去除所有中英文標(biāo)點(diǎn)符號。因?yàn)槭抢享?xiàng)目,gbk編碼,在直接使用正則匹配去除標(biāo)點(diǎn)符號時(shí),發(fā)現(xiàn)會(huì)有亂碼情況。在網(wǎng)上找了一些處理方法,多多少少都有些問題,滿足不了我的需求。但也受到了些許啟發(fā),開始寫了一個(gè)實(shí)現(xiàn)方法,有些麻煩,需要urlencode。
/*** 去除字符串中的標(biāo)點(diǎn)符號[gbk編碼環(huán)境]* @param $str* @return string*/ function punctFilter($str){//先去掉英文標(biāo)點(diǎn)符號、空格等$str = preg_replace('/[[:punct:]\s\n\t\r]/','',$str);//再匹配中文標(biāo)點(diǎn)符號 直接進(jìn)行中文標(biāo)點(diǎn)符號匹配會(huì)亂碼,因此先編碼后匹配。//若以下標(biāo)點(diǎn)還滿足不了需要,可搜索中文gbk編碼表,將對應(yīng)標(biāo)點(diǎn)符號加上即可。$pattern = '/(%a1%a0|%a1%a1|%a1%a2|%a1%a3|%a1%a4|%a1%a5|%a1%a6|%a1%a7|%a1%a8|%a1%a9|%a1%aa|%a1%ab|%a1%ac|%a1%ad|%a1%ae|%a1%af|%a1%b0|%a1%b1|%a1%b2|%a1%b3|%a1%b4|%a1%b5|%a1%b6|%a1%b7|%a1%b8|%a1%b9|%a1%ba|%a1%bb|%a1%bc|%a1%bd|%a1%be|%a1%bf|%a1%c0|%a1%c1|%a1%c2|%a1%c3|%a1%c4|%a1%c5|%a1%c6|%a1%c7|%a1%c8|%a1%c9|%a1%ca|%a1%cb|%a1%cc|%a1%cd|%a1%ce|%a1%cf|%a1%d0|%a1%d1|%a1%d2|%a1%d3|%a1%d4|%a1%d5|%a1%d6|%a1%d7|%a1%d8|%a1%d9|%a1%da|%a1%db|%a1%dc|%a1%dd|%a1%de|%a1%df|%a1%e0|%a1%e1|%a1%e2|%a1%e3|%a1%e4|%a1%e5|%a1%e6|%a1%e7|%a1%e8|%a1%e9|%a1%ea|%a1%eb|%a1%ec|%a1%ed|%a1%ee|%a1%ef|%a1%f0|%a1%f1|%a1%f2|%a1%f3|%a1%f4|%a1%f5|%a1%f6|%a1%f7|%a1%f8|%a1%f9|%a1%fa|%a1%fb|%a1%fc|%a1%fd|%a3%a0|%a3%a1|%a3%a2|%a3%a3|%a3%a4|%a3%a5|%a3%a6|%a3%a7|%a3%a8|%a3%a9|%a3%aa|%a3%ab|%a3%ac|%a3%ad|%a3%ae|%a3%ba|%a3%bb|%a3%bc|%a3%bd|%a3%be|%a3%bf|%a3%c0|%a3%db|%a3%dc|%a3%dd|%a3%de|%a3%df|%a3%e0|%a3%fb|%a3%fc|%a3%fd|%a3%fe|%a3%ff)/iu';$str = preg_replace($pattern, '', urlencode($str));return urldecode($str); }//使用示例 $str = '和≦哈1;!eo-\'\'?-+$*()‘’""“”[]-、ヾ嘿【哈】'; var_dump('punctFilter($str)',punctFilter($str)); //結(jié)果為:和≦哈1eoヾ嘿哈后來,看了鳥哥的一篇博客【分割GBK中文遭遇亂碼的解決】,頓悟的趕腳,因此優(yōu)化如下:
/*** 去除字符串中的標(biāo)點(diǎn)符號[gbk編碼環(huán)境](廢棄,看下面說明)* @param $str* @return string*/ function punctFilter($str){//先去掉英文標(biāo)點(diǎn)符號、空格等$str = preg_replace('/[[:punct:]\s\n\t\r]/','',$str);//再匹配中文標(biāo)點(diǎn)符號//第1字節(jié):A1–A9 第2字節(jié):A1–FE GB2312非漢字符號return preg_replace('/([\xa1-\xa9][\xa1-\xfe])+/', '', $str); } //使用示例 $str = '和≦哈1;!eo-\'\'?-+$*()‘’""“”[]-、ヾ嘿【哈】'; var_dump(punctFilter($str)); //結(jié)果為:和≦哈1eoヾ嘿哈若不僅想去掉標(biāo)點(diǎn)符號,還想去掉擴(kuò)充非漢字,如:ˊ ˋ ˙ – ― ‥ ‵ ℅ ℉ ↖ ↗ ↘ ↙ ∕ ∟ ∣等,修改如下:
/*** 去除字符串中的標(biāo)點(diǎn)符號[gbk編碼環(huán)境](廢棄,看下面說明)* @param $str* @return string*/ function punctFilter($str){//先去掉英文標(biāo)點(diǎn)符號、空格等$str = preg_replace('/[[:punct:]\s\n\t\r]/','',$str);//再匹配中文標(biāo)點(diǎn)符號//第1字節(jié):A1–A9 第2字節(jié):A1–FE GB2312非漢字符號//第1字節(jié):A8–A9 第2字節(jié):40–A0(7F除外) 擴(kuò)充非漢字return preg_replace('/(([\xa1-\xa9][\xa1-\xfe])|([\xa8-\xa9][\x40-\xa0]))+/', '', $str); } //使用示例 $str = '和≦哈1;!eo-\'\'?-+$*()‘’""“”[]-、ヾ嘿【哈】'; var_dump(punctFilter($str)); //結(jié)果為:和哈1eo嘿哈近日又發(fā)現(xiàn)些問題,會(huì)有中文被替換后亂碼的情況,比如“本樓盤有特價(jià)單位推出!開發(fā)商內(nèi)部價(jià)格!找小鄒買房有優(yōu)惠!”使用上述方法替換后結(jié)果為“本綠有特價(jià)禱推出開誹內(nèi)部價(jià)格找修買房有優(yōu)惠”
究其原因,直接用preg_replace()匹配時(shí),會(huì)出現(xiàn)類似如下情況:
????已知“樓盤”兩個(gè)字的gbk字符編碼為 c2a5c5cc
????使用正則(/([\xa1-\xa9][\xa1-\xfe])+/)替換時(shí),會(huì)將a5c5替換掉,只留下c2cc
????最終結(jié)果表現(xiàn)為“樓盤”替換成了“綠”字
因此最終決定一個(gè)字一個(gè)字的匹配處理,本人項(xiàng)目中標(biāo)題為50字以內(nèi),因此循環(huán)處理還可以接受,若需要處理字符串較長,還是另尋他法吧。
/*** 去除字符串中的標(biāo)點(diǎn)符號* @param $str* @return string*/ function punctFilter($str){//先去掉英文標(biāo)點(diǎn)符號、空格等$str = preg_replace('/[[:punct:]\s\n\t\r]/','',$str);//再匹配中文標(biāo)點(diǎn)符號$len = mb_strlen($str,'gbk');$newstr = $str;for($i = 0; $i < $len; $i++){$substr = mb_substr($str,$i,1,'gbk');//第1字節(jié):A1-A9 第2字節(jié):A1-FE 非漢字符號if(preg_match('/([\xa1-\xa9][\xa1-\xfe])+/', $substr,$match)){$newstr = str_replace($substr, '', $newstr);}}return $newstr; } //使用示例 $str = '和≦哈1;!eo-\'\'?-+$*()‘’""“”[]-、ヾ嘿【哈】'; var_dump(punctFilter($str)); //結(jié)果為:和≦哈1eoヾ嘿哈 //使用示例 $str = '本樓盤有特價(jià)單位推出!開發(fā)商內(nèi)部價(jià)格!找小鄒買房有優(yōu)惠!'; var_dump(punctFilter($str)); //結(jié)果為:本樓盤有特價(jià)單位推出開發(fā)商內(nèi)部價(jià)格找小鄒買房有優(yōu)惠歡迎指正補(bǔ)充。
補(bǔ)充知識(shí):
GBK編碼的單字節(jié)與雙字節(jié)
gbk編碼分兩部分,一部分是單字節(jié)編碼,另一部分是雙字節(jié)編碼。
gbk編碼中,前128個(gè)編碼都是單字節(jié)編碼。單字節(jié)編碼從00-7F,與ASCII相對應(yīng)。
在單字節(jié)編碼之后就是雙字節(jié)編碼。第一個(gè)字節(jié)范圍是81-FE。第二字節(jié)的一部分領(lǐng)域在40–7E,其他領(lǐng)域在80–FE。
這樣可以通過第一個(gè)字節(jié)就可以判斷是單字節(jié)編碼還是雙字節(jié)編碼。
摘錄自GBK編碼表與編碼字庫
雙字節(jié)編碼區(qū)又分為5部分
| GBK/1 | A1–A9 | A1–FE | 846 | 717 | GB2312 |
| GBK/2 | B0–F7 | A1–FE | 6,768 | 6,763 | GB2312漢字 |
| GBK/3 | 81–A0 | 40–FE(7F除外) | 6,080 | 6,080 | 擴(kuò)充漢字 |
| GBK/4 | AA–FE | 40–A0(7F除外) | 8,160 | 8,160 | 擴(kuò)充漢字 |
| GBK/5 | A8–A9 | 40–A0(7F除外) | 192 | 166 | 擴(kuò)充非漢字 |
| 用戶定義 | AA–AF | A1–FE | 564 | ||
| 用戶定義 | F8–FE | A1–FE | 658 | ||
| 用戶定義 | A1–A7 | 40–A0(7F除外) | 672 |
GBK漢字內(nèi)碼擴(kuò)展規(guī)范編碼表
可參考博客GBK漢字內(nèi)碼擴(kuò)展規(guī)范編碼表
總結(jié)
以上是生活随笔為你收集整理的php实现过滤中英文标点符号[gbk编码环境]的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ASP.NET 4.0 取消表单危险字符
- 下一篇: Git之简介