说这个之前,大家先看下这条语句:
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)
回车键: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/
好了,今天就说到这了,下次有时间再说,还望大家多多指教啊。有问题请在下面说就可以了。