網友ainiaa的問題是
PHP代碼如下 複製代碼 代碼如下:$words = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSRUVWXYZ!@#$%^&*()_+-=[]\\,./{}|<>?'\"你好啊我們";
$otherStr=preg_replace("/[chr(128)-chr(256)]+/is"," ",$words);
echo 'otherStr:',$otherStr;
為什麼列印的結果會是:
otherStr: ! #$% & {}| ‘”你好啊我們
麻煩問下其中Regex /[chr(128)-chr(256)]+/is 代表什麼意思?
如果/[chr(128)-chr(256)]+/is 指的是ascii碼在128到256的字元,為什麼a-zA-Z這樣的字元也被替換掉了,他們的ascii碼是小於127的。
最令人鬱悶的是為什麼ascii碼同在0-127區間”#”,”$”,”%”,”&”, “!”,” {“,”}”,”|”,” ‘”,”確沒有被替換掉????
更令人感覺神奇的是 如果把Regex修改為”/[chr(128)-chr(256)]+/s”的話,輸出的結果就變成了: otherStr: defg ijklmnopq stuvwxyz ! #$% & {}| ‘”你好啊我們
只是把Regex中的符號‘i'給去掉,結果缺失這樣的。 完全的令我理解不了。
不知各位 有何見解????
另附ascii 碼 對照表
(這個ASCII碼錶的圖我就不貼了)
回帖中,有個網友說沒解析chr(128)這些,並給出了新的解決方案。首先說下此網友回答的是正確的,先不評論他是否“知其然,且知其所以然”,這位網友沒有給出錯誤的原因。
CFC4N來回答一下這位網友:
PHP的正則的preg_match函數用的是PCRE正則引擎,這位網友的代碼中,PCRE引擎處理的Regex為【/[chr(128)-chr(256)]+/is】,後面的is是什麼呢?
在PHP的正則裡,邊界字元後面的叫模式修飾符。它會告訴引擎如何解析,處理正則。其中i修飾符表示不區分大小寫。s表示“點號通配模式”,用來讓正則裡的元字元點號【.】可以匹配分行符號,這個修飾符僅對點號【.】起作用。在這位網友的問題中,修飾符s並不起作用的。
尋找原因:
我們在來分析一下這個網友寫的Regex【[chr(128)-chr(256)]+】,Regex的PCRE引擎是如何解釋這個正則的呢?首先,我們要知道,在Regex中,中括弧【[]】表示字元組,字元組中除了串連符【-】只外,都不是元字元,也就是說,都是一般字元,當然,如果連字號出現在第一個,或者不是標識兩個字元之間範圍的,都是普通的字元橫杠“-”罷了。這裡的chr(128)只是標識ASCII碼為128(確切的說,ASCII碼只是0-127個,128到其他的,應該不叫ASCII碼了。),但是在正則裡,他仍然代表【c、h、r、(、1、2、8、)】(頓號不是,只是區分易讀的)這八個字元罷了。這個正則裡的串連字元,是哪些範圍呢?很明顯,這裡的串連字元的範圍是【)-c】,“)”ASCII碼為0×29,也就是十進位的41;“c”的ASCII碼為0×63,也就是十進位的99,那麼,他這個串連字元的範圍就是ASCII 41(chr(41))到ASCII 99(chr(99))之間的字元。也就是說,這位網友的正則的範圍是【[hr)-c(]】,就是chr(41)到chr(99)外加hr這兩個字母和前面的“(”。
網友第一次測試的時候,有修飾符i,意思就是說,不區分大小寫,那麼在chr(41)到chr(99)之間的字元,以及這些字元如果有大小寫,則包括他們的大小寫都符合匹配。都會被替換成空。其第二次測試的時候,去掉了修飾符i,進行了不區分大小寫匹配,由於其範圍只到c,但突然,再除了小寫字母的“h”、“r”,所以,測試結果會多出“defgijklmnopqstuvwxyz”。所以,他的結果出現了這些差別。
網友的運算式等同於如所示
解決辦法:
錯誤的原因找出來了,那麼,解決的辦法呢?
我們先來看看這位網友的需求,他的需求是將unicode(ASCII只是0-127位的,128之後的,應該叫UNICODE碼)的chr(128)到chr(255)之間的字元匹配,替換為空白罷了。Regex裡,對十六進位的字元匹配的表示方式有兩種,【\u】和【\x{}】,前者只能表示【\u】後面4位的十六進位數值,而後者【\x{}】則可以表示任意多的十六進位位元(寫在大括弧中)。
那麼,這個Regex該如何寫????
網友的目的是chr(128)到chr(255),那麼就是【[\u0080-\u00FF]】或者【[\x{0080}-\x{00FF}]】。
其目的是匹配中的紅框內字元
提醒一下,PHP裡正則匹配unicode字元時,需要使用u修飾符。
根據網友需求,更改正則之後的PHP代碼如下: 複製代碼 代碼如下:$words = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSRUVWXYZ!@#$%^&*()_+-=[]\\,./{}|<>?'\"你好啊我們";
$otherStr=preg_replace("//[\x{0080}-\x{00FF}]+/iu"," ",$words);
echo 'otherStr:',$otherStr;
其運行結果是仍然輸出那段字串,為什麼呢?因為哪些字串都不在chr(128)到chr(255)的範圍之內。
(測試時,注意檔案編碼為UTF-8)
以上為鄙人愚見,歡迎批評指正。