分类: 系统运维
2012-05-07 11:16:01
说明:
细说正则表达式下篇
本文为任鹏原创,每一个例子都是任鹏亲自设计并且通过调试的。本文主要讲解正则表达式的一些特殊用法,并不涉及正则的基础知识,基础知识部分请参考《细说php》一书和老师的课件
由于篇幅关系本文分为上下篇,上篇主要讲解后向引用,模式修正符,以及贪婪模式和非贪婪模式,下篇主要讲解特殊字符的转义,欢迎大家挑错^_^
1.在正则表达式中匹配特殊字符
1.1匹配正则表达式的元字符
^ $ ( ) [ ] * + ? .
|
如果要进行匹配的字符串$string中包含了以上列出的这些字符(这些字符是正则表达式元字符,在正则表达式中有特殊意义),则在正则表达式中要在元字符前面加上转义字符\,表示需要匹配这些字符而不是使用这些字符的特殊意义
例1:
$string
= 'fooa^bbar';
$pattern = '/a\^b/'; //我要在$string中查找是否包含字符串
a^b
if(preg_match($pattern,$string,$match)){
echo '找到匹配的字符串
'.$match[0];
}else{
echo '没有匹配的字符串';
}
例2:
$string =
'a*b';
$pattern = '/^[a-z]\*[a-z]$/'; //我要查看字符串$string是否只有三个字符,并且格式为
小写字母星号小写字母
if(preg_match($pattern,$string,$match)){
echo '找到匹配的字符串
'.$match[0];
}else{
echo '没有匹配的字符串';
}
例3:
$string =
'a|b';
$pattern = '/a\|b/';
$string = 'a$b';
$pattern =
'/^[a-z]\$[a-z]$/'; //注意
这里的第一个$是需要匹配的字符,因此需要加\进行转义,而第二个$前面没有加\,表示使用$的特殊意义而不是匹配这个字符,$在正则中的特殊意义就是表示字符串的结尾处,所以这个正则表达式表示的是需要查找$string是否包含以小写字母开头,以小写字母符结尾,并且中间包含一个字符$,换句话说就是查看$string是否只有三个字符,格式为
小写字母$小写字母
$string = 'a?b';
$pattern = '/a\?b/';
$string =
'a?b';
$string = 'ab';
$pattern =
'/a\??b/'; //注意第一个问号与第二个问号的不同意义,该正则可以匹配上面的两个字符串 a?b 和
ab
if(preg_match($pattern,$string,$match)){
echo '找到匹配的字符串
'.$match[0];
}else{
echo '没有匹配的字符串';
}
1.2 匹配其他特殊字符# @
%等等 这些字符不是正则表达式的元字符,在正则表达式中没有特殊意义,因此不需要转义,当然如果转义也可以
$string =
'a#b';
$pattern = '/a#b/'; 可以在$string中找到 a#b
$pattern = '/a\#b/';
//如果加上转义字符也可以
1.3 混合使用元字符和其他特殊字符
$string =
'a#^$b';
$pattern = '/a#\^\$b/';
$pattern =
'/^a#\^\$b$/';
if(preg_match($pattern,$string,$match)){
echo
'找到匹配的字符串 '.$match[0];
}else{
echo '没有匹配的字符串';
}
1.4
匹配\字符,这个非常重要
$string = 'a\b';
$string = 'a\\b'; //这两种写法都表示字符串字面量
a\b,但是最好在\前面加上\,因为单引号虽然不解析转义字符,但是单引号里面的单引号和\需要转义,所以这个 $string表示的是包含三个字符的字符串
a\b
$pattern = '/^a\\\\b$/'; //这里一定要用四个反斜线\\\\(或者三个
\\\,后面会说原因),如果你用两个\\那你悲催了,为什么要用四个呢?听我慢慢讲来。
php 中并没有正则表达式类型,php中只有8个类型,int
float bool string array object null
resource,并没有正则类型(其他语言中有的有正则类型,所以将来在写JS正则的时候会发现虽然都是用的perl风格,但是会有不同)。
php中既然没有正则类型,于是便将正则写在字符串中,所以 $pattern = '/[a]+/'; 一定要加引号!!!!!!
(在其他一些语言中不需要加引号是因为那些语言本身有正则类型 $pattern = /[a]+/; /[a]+/本身就是正则类型的,就像整型12 浮点1.23
布尔true一样,不要加引号,加了引号就变成字符串类型了,但是php中的正则一定要加引号)
我们一般将正则加到单引号中 '/^abc$/'
其实也可以加到双引号中,只不过用双引号会有一些麻烦,稍后会说
先说单引号中的转义,我们知道,单引号本身不解析转义字符,但是\和单引号本身除外
,因此如果在单引号字符串中如果需要用到\和',那么必须要在前面加上一个\作为转义,因此'a\\b'就表示字符串字面量 a\b, 'a\'b' 就表示字符串字面量
a'b。那么 'a\n\t\$b' 这个代表什么呢 因为单引号不解析转义字符,所以这里的\n\t\$会原样输出,所以'a\n\t\$b'代表字符串字面量
a\n\t\$b。那么 'a\\b' 和 'a\b' 是不是代表的相同的字符串字面量呢?答案是是的,'a\\b'
单引号中的两个\\被解析为一个\,所以'a\\b'代表字面量 a\b;而'a\b'中由于\之后是b,所以单引号不解析转义字符,所以会原样输出,因此
'a\b'也代表字符串字面量 a\b。
再来说一下双引号中的转义 双引号解析转义字符,所以 "\n\t\$"
代表的字符串字面量是 换行(非打印字符)制表符(非打印字符,相当于你按了一下Tab键)$(有特殊意义的字符)
正则表达式中的\是元字符,和^ $
* + () [] ? | . 一样有特殊意义,因此在正则中如果要匹配 \ 需要在前面转义,也就是
/a\\b/
由于php没有正则这个类型,php中的正则是写在字符串中的,这就会有一个问题,叫做双重转义,既然在字符串中和正则中\都是特殊字符,那么都需要转义,因此'/a\\\\b/'被php引擎解释为字符串字面量
/a\\b/,然后字符串 /a\\b/ 又被正则解释为 a\b,所以如果想匹配一个字符串字面量 a\b ,那么需要 $pattern =
'/^a\\\\b$/';
那么有人会问了,正则当中的\需要双重转义,那其他元字符是不是也要双重转义呢?比如要想匹配一个字符串字面量 a^b
是不是要写成 $pattern = '/a\\^b/'; 可是我们为什么写成 $pattern = '/a\^b/';
也可以呢?没错,以上两种方式都可以正确匹配字面量 a^b 。先看 '/a\\^b/' ,单引号字符串将它解释为 /a\^b/,然后正则将其解释为 a^b
。再看'/a\^b/',
单引号字符串将其解释为 /a\^b/ (因为\^会原样输出),而正则将其匹配为
a^b。所以如果遇到非反斜杠的其他元字符,例如(^ $ ()[] * + ? .
|),在单引号里面的正则表达式里只需要加一个\即可,例如'/a\^b/';而如果遇到反斜杠\,在单引号里面的正则表达式里需要双重转义,例如 '/a\\\\b/'
。
我们上面提到了 '/a\\\b/' 也可以匹配字面量 a\b ,也就是说 '/a\\\b/' 和 '/a\\\\b/' 效果相同。这是因为
'/a\\\b/' 经过单引号字符串转义为 /a\\b/ (前两个 \\转义为一个\,后面的\b原样输出),/a\\b/ 再经过正则的转义匹配字符字面量
a\b。
例子:
$string = 'a\\b'; //代表字符串字面量 a\b
$pattern =
'/^a\\\\b$/'; //匹配字符串字面量
a\b
if(preg_match($pattern,$string,$match)){
echo '找到匹配的字符串
'.$match[0];
}else{
echo '没有匹配的字符串';
}
例子:
$string =
'a\\^$#b'; //代表字符串字面量 a\^$#b
$pattern = '/^a\\\\\^\$#b$/'; // 前四个
\\\\经过单引号转义为两个 \\ 第五个\和后面的^ 也就是\^会原样输出,同理\$原样输出,所以经过单引号字符串转义为
/^a\\\^\$#b$/,再经过正则转义匹配字符串字面量
a\^$#b
if(preg_match($pattern,$string,$match)){
echo '找到匹配的字符串
'.$match[0];
}else{
echo
'没有匹配的字符串';
}
/**********************************************************************************************************************************************************************
细说正则表达式下篇结束
**********************************************************************************************************************************************************************/