PHP學(xué)習(xí)筆記之POSIX正則表達(dá)式
1 基礎(chǔ)知識(shí)
正則表達(dá)式是一種描述一段文本模式的方法。到目前為止,我們前面所用到過(guò)的精確(文字)匹配也是一種正則表達(dá)式。例如,前面我們?cè)阉鬟^(guò)正則表達(dá)式的術(shù)語(yǔ),像"shop"和"delivery"。
在PHP中,匹配正則表達(dá)式更有點(diǎn)像strstr()匹配,而不像相等比較,因?yàn)槭窃谝粋€(gè)字符串的某個(gè)位置(如果不指明則可能在字符串中的任何位置)匹配另一個(gè)字符串。例如,字符串"shop"匹配正則表達(dá)式"shop"。它也可以匹配正則表達(dá)式"h"、"ho",等。
除了精確匹配字符外,還可以用特殊字符來(lái)指定表達(dá)式的元意(meta-meaning)。例如,使用特殊字 符,可以指定一個(gè)在字符串開(kāi)始或末尾肯定存在的模式,該模式的某部分可能被重復(fù),或模式中的字符屬于特定的某一類型。此外,還可以按特殊字符的出現(xiàn)來(lái)匹 配。接下來(lái),我們將逐個(gè)討論這些變化。
2 字符集和類
使用字符集可以馬上給出比精確匹配功能還要強(qiáng)大的正則表達(dá)式。字符集可以用于匹配屬于特定類型的任何字符;事實(shí)上它們是一種通配符。
首先,可以用字符作為一個(gè)通配符來(lái)代替除換行符(\n)之外的任一個(gè)字符。例如,正則表達(dá)式:
.at
可以與"cat"、"sat"和"mat"等進(jìn)行匹配。通常,這種通配符匹配用于操作系統(tǒng)中的文件名匹配。
但是,使用正則表達(dá)式,可以更具體地指明希望匹配的字符類型,而且可以指明字符所屬的一個(gè)集合。在前面的例子中,正則表達(dá)式匹配"cat"和"mat",但也可以匹配"#at"。如果要限定它是a到z之間的字符,就可以像下面這樣指明:
[a-z]at
任何包含在方括號(hào)([])中的內(nèi)容都是一個(gè)字符類——一個(gè)被匹配字符所屬的字符集合。請(qǐng)注意,方括號(hào)中的表達(dá)式只匹配一個(gè)字符。
我們可以列出一個(gè)集合,例如:
[aeiou]
可以用來(lái)表示元音子母。
也可以描述一個(gè)范圍,正如前面用連字符那樣,也可以是一個(gè)范圍集:
[a-zA-Z]
這個(gè)范圍集代表任何的大小寫字母。
此外,還可以用集合來(lái)指明字符不屬于某個(gè)集。例如:
[^a-z]
可以用來(lái)匹配任何不在a和z之間的字符。當(dāng)把脫字符號(hào)(^)包括在方括號(hào)里面時(shí),表示否。當(dāng)該符號(hào)用在方括號(hào)的外面,則表示另外一個(gè)意思,我們稍后將詳細(xì)介紹。
3 重復(fù)
通常,讀者會(huì)希望指明某個(gè)字符串或字符類將不止一次地出現(xiàn)??梢栽谡齽t表達(dá)式中使用兩個(gè)特殊字符代替。符號(hào)“*”表示這個(gè)模式可以被重復(fù)0次或更多次,符號(hào)“+”則表示這個(gè)模式可以被重復(fù)1次或更多次。這兩個(gè)符號(hào)應(yīng)該放在要作用的表達(dá)式的后面。
例如:
[[:alnum:]]+
表示“至少有一個(gè)字母字符”。
4 子表達(dá)式
通常,將一個(gè)表達(dá)式分隔為幾個(gè)子表達(dá)式是非常有用的,例如,可以表示“至少這些字符串中的一個(gè)需要精確匹配”??梢允褂脠A括號(hào)來(lái)實(shí)現(xiàn),與在數(shù)學(xué)表達(dá)式中的方法一樣。
例如:
(very)*large
可以匹配"large"、"very large"、"very very large"等。
5 子表達(dá)式計(jì)數(shù)
可以用在花括號(hào)({})中的數(shù)字表達(dá)式來(lái)指定內(nèi)容允許重復(fù)的次數(shù)??梢灾付ㄒ粋€(gè)確切的重復(fù)次數(shù)({3}表示重復(fù)3次),或者一個(gè)重復(fù)次數(shù)的范圍({2,4}表示重復(fù)2~4次),或是一個(gè)開(kāi)底域的重復(fù)范圍({2,}表示至少要重復(fù)兩次)。
例如:
(very){1,3}
表示匹配"very"、"very very"和"very very very"。
6 定位到字符串的開(kāi)始或末尾
[a-z]模式將匹配任何包含了小寫字母字符的字符串。無(wú)論該字符串只有一個(gè)字符,或者在整個(gè)更長(zhǎng)的字符串中只包含一個(gè)匹配的字符,都沒(méi)有關(guān)系。
也可以確定一個(gè)特定的子表達(dá)式是否出現(xiàn)在開(kāi)始、末尾或在兩個(gè)位置都出現(xiàn)。當(dāng)要確定字符串中只有要找的單詞而沒(méi)有其他單詞出現(xiàn)時(shí),它將相當(dāng)有用。
脫字符號(hào)(^)用于正則表達(dá)式的開(kāi)始,表示子字符串必須出現(xiàn)在被搜索字符串的開(kāi)始處,字符“$”用于正則表達(dá)式的末尾,表示子字符串必須出現(xiàn)在字符串的末尾。
例如,以下是在字符串開(kāi)始處匹配bob:
^bob
這個(gè)模式將匹配com出現(xiàn)在字符串末尾處的字符串:
com$
***,這個(gè)模式將匹配只包含a到z之間一個(gè)字符的字符串:
^[a-z]$
7 分支
可以使用正則表達(dá)式中的一條豎線來(lái)表示一個(gè)選擇。例如,如果要匹配com、edu或net,就可以使用如下所示的表達(dá)式:
com|edu|net
8 匹配特殊字符
如果要匹配本節(jié)前面提到過(guò)的特殊字符,例如,.、{或者$,就必須在它們前面加一個(gè)反斜杠(\)。如果要匹配一個(gè)反斜杠,則必須用兩個(gè)反斜杠(\\)來(lái)表示。
在PHP中,必須將正則表達(dá)式模式包括在一個(gè)單引號(hào)字符串中。使用雙引號(hào)引用的正則表達(dá)式將帶來(lái)一些不必要的復(fù)雜性。PHP還使用反斜杠來(lái)轉(zhuǎn)義特殊字符——例如反斜杠。
如果希望在模式中匹配一個(gè)反斜杠,必須使用兩個(gè)反斜杠來(lái)表示它是一個(gè)反斜杠字符,而不是一個(gè)轉(zhuǎn)義字符。
同樣,由于相同的原因,如果希望在一個(gè)雙引號(hào)引用的PHP字符串中使用反斜杠字符,必須使用兩個(gè)反斜杠。這可 能會(huì)有些混淆,這樣要求的結(jié)果將是表示一個(gè)包含了反斜杠字符的正則表達(dá)式的一個(gè)PHP字符串需要4個(gè)反斜杠。PHP解釋器將這4個(gè)反斜杠解釋成2個(gè)。然 后,由正則表達(dá)式解釋器解析為一個(gè)。
$符號(hào)也是雙引號(hào)引用的PHP字符串和正則表達(dá)式的特殊字符。要使一個(gè)$字符能夠在模式中匹配,必須使用“\\\$”。因?yàn)檫@個(gè)字符串被引用在雙引號(hào)中,PHP解釋器將其解析為\$,而正則表達(dá)式解釋器將其解析成一個(gè)$字符。
9 在智能表單中應(yīng)用
在智能表單應(yīng)用程序中,正則表達(dá)式至少有兩種用途。***種用途是在顧客的反饋中查找特定的名詞。使用正則表達(dá) 式,可以做得更智能一些。使用一個(gè)字符串函數(shù),如果希望匹配"shop"、"customer service"或"retail",就必須做3次不同的搜索。如果使用一個(gè)正則表達(dá)式,就可以同時(shí)匹配所有3個(gè),如下所示:
shop|customer service|retail
第二個(gè)用途是驗(yàn)證程序中用戶的電子郵件地址,這需要通過(guò)用正則表達(dá)式來(lái)對(duì)電子郵件地址的標(biāo)準(zhǔn)格式進(jìn)行編碼。這 個(gè)格式中包含一些數(shù)字或標(biāo)點(diǎn)符號(hào),接著是符號(hào)“@”,然后是包括文字或數(shù)字和字符組成的字符串,后面接著是一個(gè)“.”(點(diǎn)號(hào)),后面包括文字或數(shù)字以連字 符組成的字符串,可能還有更多的點(diǎn)號(hào),直到字符串結(jié)束,它的編碼如下所示:
^[a-zA-Z0-9_\-.]+@[a-zA-Z0-9\-]+\.[a-zA-Z0-9\-.]+$
子表達(dá)式^[a-zA-Z0-9_\-.]+表示“至少由一個(gè)字母、數(shù)字、下畫線、連字符、點(diǎn)號(hào)或者這些字符組合為開(kāi)始的字符串”。請(qǐng)注意,當(dāng)在一個(gè)字符類的開(kāi)始或末尾處使用點(diǎn)號(hào)時(shí),點(diǎn)號(hào)將失去其特殊通配符的意義,只能成為一個(gè)點(diǎn)號(hào)字符。
符號(hào)“@”匹配字符“@”。
而子表達(dá)式[a-zA-Z0-9\-]+與包含文字?jǐn)?shù)字字符和連字符的主機(jī)名匹配。請(qǐng)注意,我們?nèi)コ诉B字符,因?yàn)樗欠嚼ㄌ?hào)內(nèi)的特殊字符。
字符組合“\.”匹配“.”字符。我們?cè)谧址愅獠渴褂命c(diǎn)號(hào),因此必須對(duì)其轉(zhuǎn)義,使其能夠匹配一個(gè)點(diǎn)號(hào)字符。
子表達(dá)式[a-zA-Z0-9\-\.]+$匹配域名的剩下部分,它包含字母、數(shù)字和連字符,如果需要還可包含更多的點(diǎn)號(hào)直到字符串的末尾。
不難發(fā)現(xiàn),有時(shí)一個(gè)無(wú)效的電子郵件地址也會(huì)符合這個(gè)正則表達(dá)式。找到所有無(wú)效電子郵件幾乎是不可能的,但是經(jīng) 過(guò)分析,情形將會(huì)有所改善。可以按許多不同的方式精化這個(gè)表達(dá)式。例如,可以列出所有有效的***域(TLD)。當(dāng)對(duì)某些對(duì)象進(jìn)行限制的時(shí)候,請(qǐng)千萬(wàn)小心, 因?yàn)榭赡芘懦?%的有效數(shù)據(jù)的校驗(yàn)函數(shù)比允許出現(xiàn)10%的無(wú)效數(shù)據(jù)的校驗(yàn)函數(shù)還要麻煩。
“每個(gè)星期讀一本書,那么一年就讀了50本書” 加油。。。 別給自己太多放棄的理由。