說這個之前,大家先看下這條語句:
preg_replace("/\<\?\=(\\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\[\]\"\'\$\x7f-\xff]*)\?\>/s", "\\1", $p2));
此例是應用preg_replace()函式,當你第一 次看時,是不是有如下幾點疑問:
1.\<\?\=,不理解為何要用上轉義符號\,看了語法教程,正則中並沒有這樣的寫法,只有\s、\d、\w等七種,而且雙引號中包含字串也不需要用到轉義字元啊(指\ ? =這三種),不明白為何要用上轉義字元?
2.\\\$,這點如何理解?是匹配反斜槓和$這個定位字元($表示匹配的模式出現在匹配物件的末尾),還是理解為\\和\$(這個表示$字元)?個人理解是匹配\\和\$,假如我的理解是正確的,那\\\$這第一個反斜槓是何作用(後面的\\$則是匹配$,代表變數名)?
3.\x7f-\xff,這是匹配ASCII擴充套件碼的,我測試一下下面的程式碼:
1 <? 2 $str="ǎ"; 3 print preg_replace("/\x7f-\xff/","erw",$str); 4 ?>
但執行結果是隻輸出ǎ,不匹配,但我檢視了ASCII擴充套件碼,ǎ是屬於擴充套件碼的呀,為何不匹配呢?是不是我哪裡寫錯了?還有,PHP變數名命名規則中規定變數名不能取副檔名中的任何一個字元啊,但上面的\\\$[a-zA-Z_\x7f-\xff如果是匹配變數名的話,這\x7f-\xff又有何作用呢?變數名不允許取自這些字元,用上沒有意義啊?
4.
$template = preg_replace("/\{(\\\$[a-zA-Z0-9_\[\]\'\"\$\x7f-\xff]+)\}/s", "<?=\\1".PHP_CLOSE_TAG, $template);
你不會說這句好象是匹配變數名稱的,呵呵,但此例的\[\]又是匹配什麼,是不是看了半天也沒明白,另外\'\"是匹配單引號和雙引號的,\$\x7f-\xff是匹配ASCII擴充套件碼的,但單引號及雙引號還有ASCII擴充套件碼並不能用於變數命名呀,為何要寫上這樣的匹配條件,是不是有點不解啊。還有,大括號用來精確指定匹配元字元出現的次數(語法資料上是這樣寫的),但是你有沒有發現上面的大括號好像並不是這個作用呀,那用上大括號是何作用呢?
先別急,在解答之前,先讓大家看一下熟悉的ASCII碼及其擴充套件碼。
ASCII 碼使用指定的7 位或8 位二進位制數組合來表示128 或256 種可能的字元。標準ASCII 碼也叫基礎ASCII碼,使用7 位二進位制數來表示所有的大寫和小寫字母,數字0 到9、標點符號, 以及在美式英語中使用的特殊控制字元。其中:
0~31及127(共33個)是控制字元或通訊專用字元(其餘為可顯示字元),如控制符:LF(換行)、CR(回車)、FF(換頁)、DEL(刪除)、BS(退格)、BEL(響鈴)等;通訊專用字元:SOH(文頭)、EOT(文尾)、ACK(確認)等;ASCII值為8、9、10 和13 分別轉換為退格、製表、換行和回車字元。它們並沒有特定的圖形顯示,但會依不同的應用程式,而對文字顯示有不同的影響。
32~126(共95個)是字元(32sp是空格),其中48~57為0到9十個阿拉伯數字
65~90為26個大寫英文字母,97~122號為26個小寫英文字母,其餘為一些標點符號、運算子號等。
|
標準ASCII表
|
常見ASCII碼的大小規則1)數字0~9比字母要小。如"7"<"F";
2)數字0比數字9要小,並按0到9順序遞增。如"3"<"8"
3)字母A比字母Z要小,並按A到Z順序遞增。如"A"<"Z"
4)同個字母的大寫字母比小寫字母要小。如"A"<"a"。
記住幾個常見字母的ASCII碼大小:
“換行LF”為0x0A;“回車CR”為0x0D;空格為0x20;"0"為0x30; "A"為0x41;"a"為0x61。
另外還有128-255的ASCII字元查詢ASCII技巧方便查詢ASCII碼對應的字元:新建一個文字文件,按住ALT+要查詢的碼值(注意,這裡是十進位制)
鬆開即可顯示出對應字元。例如:按住ALT+97,則會顯示出‘a'。
|
虛擬鍵盤按鍵的ASCII值ESC鍵VK_ESCAPE (27)
Enter鍵:VK_RETURN (13)
TAB鍵:VK_TAB (9)
Caps Lock鍵:VK_CAPITAL (20)
Shift鍵:VK_SHIFT (16)
Ctrl鍵:VK_CONTROL (17)
Alt鍵:VK_MENU (18)
空格鍵:VK_SPACE (32)
退格鍵:VK_BACK (8)
左徽標鍵:VK_LWIN (91)
右徽標鍵:VK_RWIN (92)
滑鼠右鍵快捷鍵:VK_APPS (93)
Insert鍵:VK_INSERT (45)
Home鍵:VK_HOME (36)
Page Up:VK_PRIOR (33)
PageDown:VK_NEXT (34)
End鍵:VK_END (35)
Delete鍵:VK_DELETE (46)
方向鍵(←):VK_LEFT (37)
方向鍵(↑):VK_UP (38)
方向鍵(→):VK_RIGHT (39)
方向鍵(↓):VK_DOWN (40)
F1鍵:VK_F1 (112)
F2鍵:VK_F2 (113)
F3鍵:VK_F3 (114)
F4鍵:VK_F4 (115)
F5鍵:VK_F5 (116)
F6鍵:VK_F6 (117)
F7鍵:VK_F7 (118)
F8鍵:VK_F8 (119)
F9鍵:VK_F9 (120)
F10鍵:VK_F10 (121)
F11鍵:VK_F11 (122)
F12鍵:VK_F12 (123)
Num Lock鍵:VK_NUMLOCK (144)
小鍵盤0:VK_NUMPAD0 (96)
小鍵盤1:VK_NUMPAD1 (97)
小鍵盤2:VK_NUMPAD2 (98)
小鍵盤3:VK_NUMPAD3 (99)
小鍵盤4:VK_NUMPAD4 (100)
小鍵盤5:VK_NUMPAD5 (101)
小鍵盤6:VK_NUMPAD6 (102)
小鍵盤7:VK_NUMPAD7 (103)
小鍵盤8:VK_NUMPAD8 (104)
小鍵盤9:VK_NUMPAD9 (105)
小鍵盤。:VK_DECIMAL (110)
小鍵盤*:VK_MULTIPLY (106)
小鍵盤+:VK_ADD (107)
小鍵盤-:VK_SUBTRACT (109)
小鍵盤/:VK_DIVIDE (111)
Pause Break鍵:VK_PAUSE (19)
Scroll Lock鍵:VK_SCROLL (145)
|
本文寫到這,還真是見笑了,正則真的很複雜(對新手來說),好多地方都不明白,讓人頭都搞大,當然本人水平有限,還希望能得到高手們的指點.
正則是個好東西,又是個壞東西.她好如仙女,讓你做神仙眷侶;壞如魔鬼,讓你生不如死.沒有什麼特別的書能夠說講得好,但是最基本的PERC的又是最基礎講得最好的.
一切需要悟性,用,則學一輩子,也許終此一生門外徘徊,但是不要氣餒,至少你學過了.不用,則當機立斷,終老一生時,你會慶幸當初沒有學,否則一輩子的光陰白白耗費在幾個變來換去的字元上!
其實上面的/\x7f-\xff/表示三個字元,而/[\x7f-\xff]/才表示一個範圍之內的字元,繼續往下寫,
我們寫一段程式碼測試下:
<? $str="ǎ"; print preg_replace("/[\x7f-\xff]/","erw",$str); ?>
呵呵,看到了吧,總算有字元輸出了,執行結果如下:
erwerw
是不是很奇怪啊,只有一個ǎ啊,為何有兩次替換的動作呢?另外,/\x7f-\xff/表示三個字元,這是哪三個字元呢?你想半天也不會明白是怎麼回事,還是繼續向下看吧。
看來還是得修改下程式碼:
<? $str="ǎ"; print preg_replace("/[\x7f-\xff]{2}/","erw",$str); ?>
OK,執行結果:
ǎ
這下總算輸出預期結果了,但為何非要加上{2}才會輸出這個結果呢?這大括號用來精確指定匹配元字元出現的次數,上面的[\x7f-\xff]同[z-z]不也一樣的嗎?只要匹配其中的一個即可完成替換動作,ǎ也符合這個條件啊,但事實是不加上{2}就不會輸出一個ǎ這個結果,想了半天,大家是不是還是不解,讓我再教教你們吧!
我再舉一個例子:
<? $str="a"; print preg_replace("/[a-z]/","1",$str); ?>
執行結果:
1
看,只會替換一次的,那我上面的例子又是怎麼回事呢 ...
這是因為127以下的字元是7bit,擴充套件字元是8bit,這7bit和8bit對於preg_replace()函式是有影響的?
還有下面的一個例子:
$str = "超越PHP"; if (preg_match("/^[".chr(0xa1)."-".chr(0xff)."]+$/", $str)) { echo "這是一個純中文字串"; } else { echo "這不是一個純中文字串"; }
是不是搞不懂0xa1、0xff這些進位制是如何轉換的呢?
漢字是雙位元組的,下面摘自php中文手冊:
單引號或雙引號括起來的 PHP 字串中的反斜線有特殊含義。因此必須用正規表示式的 \\ 來匹配 \,我用如下程式碼測試:
<? $str="\"; print preg_replace("/\\/","5",$str); ?>
什麼也沒有輸出,顯然並沒有匹配條件,再修改如下:
<? $str="\"; print preg_replace("/\\\/","5",$str); ?>
是沒有任何輸出,最後修改如下:
<? $str="\\"; print preg_replace("/\\\/","5",$str); ?>
算OK了,輸出5,條件匹配了
但對照上面所說的匹配條件(單引號或雙引號括起來的 PHP 字串中的反斜線有特殊含義。因此必須用正規表示式的 \\ 來匹配 \),兩者是不是感覺有點不對應啊,字串中如果帶有反斜槓必須要用\\才能輸出(一個反斜槓不會有任何輸出的),那正則中必須要以轉義字元\再加兩個反斜槓才能匹配反斜槓啊,我最後的示例就是這樣,但按照手冊所說的須用正規表示式的 \\ 來匹配 \,無法成功匹配啊,是不是還是沒有徹底明白,按上面的說法\\\$的確是匹配一個反斜槓和一個$符號(\\匹配一個反斜槓,\$匹配$符號),我們再測試了一下如下程式碼:
<? $str="\\\$"; print preg_replace("/\\\$/","5",$str); ?>
輸出\5,但怎麼都不能理解正規表示式的 \\ 來匹配 \這點,哪裡理解出錯了呢。
接下來的[\]依上面是對應[, ],但測試如下程式碼無論如何都不能通過:
<? $str=","; print preg_replace("/[\]/","5",$str); ?>
只有將[\]改為[,]才會匹配條件。
最後,\x7f-\xff是匹配127-255的ascii碼,上面的工作上已測試瞭如下程式碼:
<? $str="ǎ"; print preg_replace("/[\x7f-\xff]{2}/","erw",$str); ?>
執行一切正常,但必須要加上{2}這個條件才行,同時我已經說過127以下的字元是7bit,擴充套件字元是8bit,那這位元組數不一樣,對於preg_replace()函式的執行具體影響在哪兒?
這主要是 因為在字串之中,\本來就會轉義的.關鍵時刻看下手冊:
ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/
好了,今天就說到這了,下次有時間再說,還望大家多多指教啊。有問題請在下面說就可以了。