PHP 新手入門(mén)之正則表達(dá)式
1.定界符
什么是定界符?
所謂定界符,就是定一個(gè)邊界,內(nèi)容要寫(xiě)在這個(gè)邊界內(nèi)
// 這就是正則表達(dá)式中的定界符 表達(dá)式要寫(xiě)在//中間
即/a-z/
2.定界符有哪些?
除了字母、數(shù)字和反斜線\以外的任何字符都可以為定界符號(hào),比如 | |、//、{}、!!等等,但是需要注意,如果沒(méi)有特殊需要,我們都應(yīng)用作為正則表達(dá)式的定界符號(hào)
3.正則表達(dá)式的構(gòu)成
一個(gè)標(biāo)準(zhǔn)的正則表達(dá)式由3部分構(gòu)成:
(1).分隔符
(2).表達(dá)式
(3).修飾符
分隔符:分隔符用來(lái)包裹表達(dá)式,可以是除了特殊字符以外的任何字符,常用的分隔符“/”
表達(dá)式:表達(dá)式是由一些特殊字符(元字符)和非特殊字符(文本字符)組成
修飾符:在PHP正則表達(dá)式里面的修飾符可以改變正則的很多特性,使得正則表達(dá)式更加適合你的需要(注意:修飾符對(duì)于大小寫(xiě)是敏感的,這意味著"e"并不等于"E")
正則表達(dá)式中的修飾符有哪些呢?
PHP正則表達(dá)式修飾符的種類及介紹:
◆i :如果在修飾符中加上"i",則正則將會(huì)取消大小寫(xiě)敏感性,即"a"和"A" 是一樣的。
◆m:默認(rèn)的正則開(kāi)始"^"和結(jié)束"$"只是對(duì)于正則字符串如果在修飾符中加上"m",那么開(kāi)始和結(jié)束將會(huì)指字符串的每一行:每一行的開(kāi)頭就是"^",結(jié)尾就是"$"。
◆s:如果在修飾符中加入"s",那么默認(rèn)的"."代表除了換行符以外的任何字符將會(huì)變成任意字符,也就是包括換行符!
◆x:如果加上該修飾符,表達(dá)式中的空白字符將會(huì)被忽略,除非它已經(jīng)被轉(zhuǎn)義。
◆e:本修飾符僅僅對(duì)于replacement有用,代表在replacement中作為PHP代碼。
◆A:如果使用這個(gè)修飾符,那么表達(dá)式必須是匹配的字符串中的開(kāi)頭部分。比如說(shuō)"/a/A"匹配"abcd"。
◆E:與"m"相反,如果使用這個(gè)修飾符,那么"$"將匹配絕對(duì)字符串的結(jié)尾,而不是換行符前面,默認(rèn)就打開(kāi)了這個(gè)模式。
◆U:和問(wèn)號(hào)的作用差不多,用于設(shè)置"貪婪模式"。
正則表達(dá)式中的原子
原子是正則表達(dá)示里面的最小單位,原子說(shuō)白了就是需要匹配的內(nèi)容。一個(gè)成立的正則表達(dá)示當(dāng)中必須最少要有一個(gè)原子
說(shuō)明:我們見(jiàn)到的空格、回車(chē)、換行、0-9、A-Za-z、中文、標(biāo)點(diǎn)符號(hào)、特殊符號(hào)全為原子。在做原子的實(shí)例前我們先來(lái)講解一個(gè)函數(shù),preg_match
語(yǔ)法:int preg_match ( string $正則 , string $字符串 [, array &$結(jié)果] )
上面是preg_match常用的主要幾個(gè)參數(shù)。我在上面將另外幾個(gè)參數(shù)沒(méi)有列出來(lái)。因?yàn)?,另外兩個(gè)參數(shù)太不常用了。
我們來(lái)通過(guò)實(shí)驗(yàn)來(lái)證明:
<?php header("Content-type: text/html; charset=utf-8");//設(shè)置編碼 $zz = '/a/'; $string = 'ddfdjjvai2jfvkwkfi24'; if(preg_match($zz, $string, $matches)){ echo '匹配到了,結(jié)果為:'; var_dump($matches); }else{ echo '沒(méi)有匹配到'; } ?>
注:$zz 為正則表達(dá)式的規(guī)則 $string 是一個(gè)字符串,本例是判斷這個(gè)字符串是否滿足匹配的正則表達(dá)式,如果滿足,輸出結(jié)果,不滿足,輸出信息
特殊標(biāo)識(shí)的原子
\d 匹配0-9
<?php header("Content-type: text/html; charset=utf-8");//設(shè)置編碼 // \d的用法 $zz = '/\d/'; $string = '我愛(ài)喝9你愛(ài)不愛(ài)喝'; if(preg_match($zz, $string, $matches)){ echo '匹配到了,結(jié)果為:'; var_dump($matches); }else{ echo '沒(méi)有匹配到'; } ?>
\D 除了0-9以外的所有字符
<?php // \D 匹配出0-9以外的所有字符 $zz = '/\D/'; $string = '12124323453453'; if(preg_match($zz, $string, $matches)){ echo '匹配到了,結(jié)果為:'; var_dump($matches); }else{ echo '沒(méi)有匹配到'; } ?>
\w a-z A-Z0-9_
<?php // \w 匹配a-zA-Z0-9 還有下劃線 $zz = '/\w/'; $string = '新中_國(guó)萬(wàn)歲呀萬(wàn)歲'; if(preg_match($zz, $string, $matches)){ echo '匹配到了,結(jié)果為:'; var_dump($matches); }else{ echo '沒(méi)有匹配到'; } ?>
\W 與\w相反
<?php //\W 除a-zA-Z0-9_ 以外的所有字符 $zz = '/\W/'; $string = '......'; if(preg_match($zz, $string, $matches)){ echo '匹配到了,結(jié)果為:'; var_dump($matches); }else{ echo '沒(méi)有匹配到'; } ?>
\s 匹配所有的空白字符
<?php // \s 匹配所有的空白字符 $zz = '/\s/'; $string = "中國(guó)萬(wàn) 歲"; if(preg_match($zz, $string, $matches)){ echo '匹配到了,結(jié)果為:'; var_dump($matches); }else{ echo '沒(méi)有匹配到'; } ?>
\S 非空字符
<?php // \S 匹配非空字符 $zz = '/\S/'; $string = " a "; if(preg_match($zz, $string, $matches)){ echo '匹配到了,結(jié)果為:'; var_dump($matches); }else{ echo '沒(méi)有匹配到'; } ?>
[] 指定范圍的原子
<?php // [] 指定原子范圍 $zz = '/[0-5]\w+/'; $string = '6a'; $string1 = '1C'; if(preg_match($zz, $string, $matches)){ echo '匹配到了,結(jié)果為:'; var_dump($matches); }else{ echo '沒(méi)有匹配到'; } ?>
大家看這些\w \s \W \S 是有點(diǎn)記不住的,所以下面有等價(jià)的出來(lái),效果是和\s \w 等等是一樣的
+ 匹配最少1次前面的字符
<?php header("Content-type: text/html; charset=utf-8");//設(shè)置編碼 $zz = '/\d+/'; $string = "迪奧和奧迪250都是我最愛(ài)"; //待會(huì)兒再試試中間沒(méi)有0-9的情況 //$string = "迪奧和奧迪都是我最愛(ài)"; if(preg_match($zz, $string, $matches)){ echo '匹配到了,結(jié)果為:'; var_dump($matches); }else{ echo '沒(méi)有匹配到'; } ?>
* 匹配0次或者任意多次前面的字符
<?php $zz = '/\w*/'; $string = "!@!@!!@#@!$@#!"; //待會(huì)兒再試試中間沒(méi)有0-9的情況 //$string1 = "!@#!@#!abcABC#@#!"; if(preg_match($zz, $string, $matches)){ echo '匹配到了,結(jié)果為:'; var_dump($matches); }else{ echo '沒(méi)有匹配到'; } ?>
? 前面的字符出現(xiàn)0次或者1次,可有可無(wú)
<?php $zz = '/ABC\d?ABC/'; $string = "ABC1ABC"; //待會(huì)兒再試試中間沒(méi)有0-9的情況 //$string1 = "ABC888888ABC"; //$string2 = "ABCABC"; if(preg_match($zz, $string, $matches)){ echo '匹配到了,結(jié)果為:'; var_dump($matches); }else{ echo '沒(méi)有匹配到'; } ?>
. (點(diǎn)) 匹配除\n以外的所有字符
<?php $zz = '/gg.+gg/'; $string = "ABC1ABC"; if(preg_match($zz, $string, $matches)){ echo '匹配到了,結(jié)果為:'; var_dump($matches); }else{ echo '沒(méi)有匹配到'; } ?>
|(豎線),或者,優(yōu)先級(jí)最低
<?php $zz = '/abc|bcd/'; $string1 = "abccd"; $string2 = "ggggbcd"; if (preg_match($zz, $string1, $matches)) { echo '匹配到了,結(jié)果為:'; var_dump($matches); } else { echo '沒(méi)有匹配到'; } ?>
通過(guò)上面的實(shí)例我們看出:
1. 最開(kāi)始我匹配的想法是想匹配的是abccd或者是abbcd??墒牵ヅ?string1和$string2,匹配出來(lái)的結(jié)果卻是abc和bcd.
2. 實(shí)現(xiàn)了或者匹配,匹配出來(lái)了abc或者是bcd。它還沒(méi)有字符串連續(xù)在一起的優(yōu)先級(jí)高
^ (抑揚(yáng)符),必須要以^之后的字符串開(kāi)始
<?php $zz = '/^張杰好帥\w+/'; $string1 = "張杰好帥abccdaaaasds"; //$string2沒(méi)有以張杰好帥開(kāi)始 $string2 = "帥abccdaaaasds"; if (preg_match($zz, $string1, $matches)) { echo '匹配到了,結(jié)果為:'; var_dump($matches); } else { echo '沒(méi)有匹配到'; } ?>
通過(guò)實(shí)驗(yàn)發(fā)現(xiàn)以下結(jié)論:
1. $string1匹配成功,$string2沒(méi)有匹配成功
2. 因?yàn)?string1是以指定的字符開(kāi)始的
3. 而$string2并沒(méi)有以^之后的字符開(kāi)始
4. 翻譯這個(gè)正則的意思就是:以要李文凱好帥開(kāi)始后面接a-zA-Z0-9_最少一個(gè)字符。
$ (美元符)必須要以$之前的字符結(jié)束
<?php $zz = '/\d+努力$/'; $string1 = "12321124333努力"; //$string2 $string2 = "12311124112313力"; if (preg_match($zz, $string1, $matches)) { echo '匹配到了,結(jié)果為:'; var_dump($matches); } else { echo '沒(méi)有匹配到'; } ?>
注:
$string1 匹配成功,而$string2匹配不成功
$之前的字符是\d+,后面接著中文的努力。
因此,匹配的是這一個(gè)整體。\d指的是0-9的整型,+號(hào)代表最少一個(gè)0-9
{m}有且只能出現(xiàn)m次
<?php $zz = '/喝\d{1,3}酒/'; $string1 = "喝9酒"; //$string2 = "喝988酒"; if (preg_match($zz, $string1, $matches)) { echo '匹配到了,結(jié)果為:'; var_dump($matches); } else { echo '沒(méi)有匹配到'; } ?>
注:上例中\(zhòng)d{1,3}我規(guī)定了0-9只能出現(xiàn)1次,2次或者3次。其它次數(shù)都是錯(cuò)的
{m,} 至少m次,最大次數(shù)不限制
<?php $zz = '/喝\d{2,}/'; $string1 = "喝9"; //$string2 = "喝98"; //$string3 = "喝98122121"; if (preg_match($zz, $string1, $matches)) { echo '匹配到了,結(jié)果為:'; var_dump($matches); } else { echo '沒(méi)有匹配到'; } ?>
上例中\(zhòng)d{2,}我規(guī)定喝后面的0-9最少出現(xiàn)兩次,最多次數(shù)不限。因此$string1是匹配不成功的,$string2是匹配成功的。$string3是匹配成功的
正則表達(dá)式的技巧
寫(xiě)一點(diǎn)、測(cè)一點(diǎn)
因?yàn)椋覀冃枰粩嗟恼齽t,用preg_match對(duì)比是不是能匹配成功。成功了,再寫(xiě)后面的一點(diǎn)。直到寫(xiě)完,全部匹配成功為止!
接下來(lái)我們寫(xiě)個(gè)整合的例子 郵箱的正則表達(dá)式
第一步:把郵箱的格式全部列出來(lái)
liwenkai@phpxy.com
iwenkai@corp.baidu.cm
iwenkai@126.com
_w_k@xxx.com
2345@qq.com
先匹配@之前的字符 \w+(因?yàn)槭?-9A-Za-z_)
第二個(gè)跟一個(gè)@符
第三個(gè)再寫(xiě)上[a-zA-Z0-9-]+ 因?yàn)閝q和126這些主域名是不能有下
劃線的
corp.baidu. 或者是126. 通常郵箱后綴都是這樣的。所以我們可以寫(xiě)成:([a-zA-Z0-9-]+.){1,2}
上面的是將.轉(zhuǎn)義,讓它是本身的意思。括號(hào)重復(fù)的區(qū)間最少一次,最多兩次。
后面接下com|cn|org|gov.cn|net|edu.cn等就可以了
<?php header("Content-type: text/html; charset=utf-8");//設(shè)置編碼 $zz = '/\w+@([a-zA-Z0-9-]+.){1,2}(com|cn|org|gov.cn|net|edu.cn)/'; $string1 = "k53981@qq.com"; if (preg_match($zz, $string1, $matches)) { echo '匹配到了,結(jié)果為:'; var_dump($matches); } else { echo '沒(méi)有匹配到'; } ?>