成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

正則表達(dá)式基本知識(shí)(php)

lunaticf / 2443人閱讀

摘要:字符組字符組就是一組字符,在正則表達(dá)式中,它表示在同一個(gè)位置可能出現(xiàn)的各種字符。放在正則表達(dá)式的開頭,表示定位到字符串的起始位置用在正則表達(dá)式的末尾,表示定位到字符串的結(jié)束位置。

這里的知識(shí)點(diǎn)基本上是《正則指引》的讀書筆記,只是每個(gè)知識(shí)點(diǎn)的示例代碼用php來實(shí)現(xiàn)。

1. 字符組

字符組(Character Class)就是一組字符,在正則表達(dá)式中,它表示“在同一個(gè)位置可能出現(xiàn)的各種字符”。
寫法:[ab]、[314]、[#.?]

字符組的基本用法

[...]

preg_match("/[0123456]/", "5");    // => 1
preg_match("/[abc123]/", "5");    // => 0
范圍表示法(range)

[x-y]表示xy整個(gè)范圍內(nèi)的字符。如,[0123456789]表示為[0-9],[abcdefghijk]表示為[a-k]。

為什么是[0-9],而不是[9-0]?
因?yàn)?b>-表示的范圍一般是根據(jù)字符對(duì)應(yīng)的碼值(Code Point)來確定的。典型地有ACSⅡ編碼。在ACSⅡ編碼中,0~9的碼值是48~57,a~z的碼值是97~122,A~Z的碼值是65~90。

preg_match("/[0-9]/", "5");    // => 1
preg_match("/[a-z]/", "5");    // => 0
preg_match("/[0-9a-fA-F]/", "0");    // 16進(jìn)制
字符組簡記法(shorthands)

提供比范圍表示法更簡潔的表示方法,如d表示[0-9]w表示[0-9a-zA-z_]。

php中支持的字符組簡記:

d 所有的數(shù)字,即[0-9]

D 所有的非數(shù)字,與d互斥

w 所有的單詞字符(字符、數(shù)字、下劃線),即[0-9a-zA-Z_]

W 所有的非單詞字符,與W互斥

s 所有的空白字符,包括空格、制表符、回車符、換行符等空白字符

S 所有的非空白字符,與s互斥

preg_match("/d/", "8");    // => 1
preg_match("/d/", "a");    // => 0
preg_match("/d[a-z]/", "a");    // => 1

preg_match("/w/", "a");    // => 1
preg_match("/w/", "6");    // => 1
preg_match("/w/", "_");    // => 1

preg_match("/s/", " ");    // => 1
preg_match("/s/", "	");    // => 1
preg_match("/s/", "
");    // => 1
元字符與轉(zhuǎn)義

在范圍表示法中,字符組中的橫線-不能匹配橫線字符,而是用來表示范圍,這類字符叫做元字符(meta-character)。元字符除了-還有開方括號(hào)[、閉剛括號(hào)]^$等,它們都有特殊的意義。
當(dāng)元字符想要表示普通字符的含義時(shí)(如-就只想表示橫線字符),就需要轉(zhuǎn)義處理(在元字符前加反斜線字符)。對(duì)于-,有一個(gè)例外情況,就是當(dāng)它緊跟著字符組中的開括號(hào)[時(shí),它就表示普通橫線字符,此時(shí)不用轉(zhuǎn)義。

preg_match("/[0-9]/", "-");    // => 1
preg_match("/[0-9]/", "8");    // => 0
preg_match("/[0-9]/", "0");    // => 1

preg_match("/[-09]/", "-");    // => 1

preg_match("/[0-9]/", "-");    // => 1
preg_match("/[0-9]/", "-");    // => 1

仔細(xì)看上面第一個(gè)表達(dá)式和最后兩個(gè)表示式。這里要注意:

在php中,字符串既可以用單引號(hào)標(biāo)注也可以用雙引號(hào)標(biāo)注。兩者的主要區(qū)別在于,雙引號(hào)字符串可以插值,二單引號(hào)字符串不能;另外,雙引號(hào)字符串會(huì)處理字符串轉(zhuǎn)義,二單引號(hào)字符串不會(huì)

正則表達(dá)式是以字符串的方式提供的。在php中,雙引號(hào)字符串本身也有關(guān)于轉(zhuǎn)義的規(guī)定(如""、" "、" "等),因此"0-9""0-9"是等價(jià)的。

那么最后一個(gè)表達(dá)式為什么也可以匹配呢?這是因?yàn)?,盡管php的正則表達(dá)式用字符串文字給出,但它與常見的字符串不完全一樣——如果某個(gè)轉(zhuǎn)義序列可以有字符串識(shí)別,則對(duì)其進(jìn)行轉(zhuǎn)義處理;否則,將整個(gè)轉(zhuǎn)義序列“原封不動(dòng)”地保存下來。

因此,在正則表達(dá)式中轉(zhuǎn)義要小心,在php中,使用單引號(hào)字符串來構(gòu)建正則表達(dá)式會(huì)比雙引號(hào)字符串更簡單明了。

排除型字符組(Negated Character Class)

在方括號(hào)[…]中列出希望匹配的所有字符叫做“普通字符組”。在開方括號(hào)[之后緊跟一個(gè)脫字符^,寫作[^…],表示“在當(dāng)前位置,匹配一個(gè)沒有列出的字符”。例如,[^0-9]匹配非數(shù)字字符。

preg_match("/[^0-9][0-9]/", "A8");    // => 1

排除型字符組中的緊跟著開方括號(hào)[的脫字符^也是元字符,如果要匹配尖括號(hào)字符,需要進(jìn)行轉(zhuǎn)義處理。但是,不緊跟著開方括號(hào)[^就是普通字符,不需要轉(zhuǎn)義。

preg_match("/[^0-9]/", "0");    // => 0
preg_match("/[^0-9]/", "0");    // => 1
preg_match("/[^0-9]/", "^");    // => 1
preg_match("/[0-9^]/", "^");    // => 1
POSIX字符組

之前介紹的字符組,都屬于Perl衍生出來的正則表達(dá)式流派(Flavor),這個(gè)流派叫做PCRE(Per Compatible Regular Expression)。正則表達(dá)式還有其他流派,比如POSIX(Portable Operating System Interface for unix),它是一系列規(guī)范,定義了UNIX操作系統(tǒng)應(yīng)當(dāng)支持的功能,其中也包括了正則表達(dá)式的規(guī)范。

常見的[a-z]形式的字符組,在POSIX規(guī)范中仍然獲得支持,稱作POSIX方括號(hào)表達(dá)式。POSIX方括號(hào)表達(dá)式中的不是用來轉(zhuǎn)義的,如[d]就只能匹配d兩個(gè)字符。這里涉及到]、-這兩個(gè)特殊字符,在POSIX規(guī)范中,緊接在開方括號(hào)[之后的]才表示閉方括號(hào)字符,緊挨在閉方括號(hào)]之前的-才表示橫線字符。

對(duì)于PCRE規(guī)范中的d、w、s等字符組簡記法,POSIX中有類似的東西,叫做POSIX字符組。在ASCⅡ語言環(huán)境(locale)中,常見的POSIX字符組及其含義如下:

POSIX字符組 說明 ACSⅡ字符組 等價(jià)的PCRE簡記法
[:alnum:] 字母和數(shù)字 [0-9a-zA-Z]
[:alpha:] 字母 [a-zA-Z]
[:ASCⅡ] ASCⅡ字符 [x00-x7F]
[:blank:] 空格字符和制表字符 [ ]
[:cntrl:] 控制字符 [x00-x1Fx7F]
[:digit:] 數(shù)字字符 [0-9] d
[:graph:] 空白字符之外的字符 [x21-x7E]
[:lower:] 小寫字母字符 [a-z]
[:print:] 類似[:graph:],但包括空白字符 [x20-x7E]
[:punct:] 標(biāo)點(diǎn)符號(hào) [][!"#$%&"()*+,./:;<=>?@^_`{ }~-]
[:space:] 空白字符 [ vf] s
[:upper:] 大寫字母 [A-Z]
[:word:] 字母字符 [A-Za-z0-9_] w
[:xdigit:] 十六進(jìn)制字符 [A-Fa-f0-9]

php中有專門處理POSIX正則的函數(shù),但從5.3.0開始已經(jīng)廢棄了。這里只是了解一下相關(guān)知識(shí)。

2. 量詞

這里首先介紹一下^$兩個(gè)特殊字符,在上一章的元字符與轉(zhuǎn)義一節(jié)提到過這兩個(gè)特殊字符。
^放在正則表達(dá)式的開頭,表示“定位到字符串的起始位置”;$用在正則表達(dá)式的末尾,表示“定位到字符串的結(jié)束位置”。

preg_match("/wd/", "1a2b");   // => 1
preg_match("/^wd/", "1a2b");  // => 0 必須以字母開頭
preg_match("/wd$/", "1a2b");  // => 0 必須以數(shù)字結(jié)尾
preg_match("/^wd/", "a2b");   // => 1
preg_match("/wd$/", "1a2");   // => 1
preg_match("/^wd$/", "1a2");  // => 0 開頭必須是字母,結(jié)尾必須是數(shù)字
preg_match("/^wd$/", "a2");   // => 1
量詞的一般形式

如果要匹配一個(gè)郵政編碼(6位數(shù)字),目前能寫出來的正則表達(dá)式是^ffffdffffd$

preg_match("/^ffffdffffd$/", "100010");   // => 1
preg_match("/^ffffdffffd$/", "10001035"); // => 0
preg_match("/^ffffdffffd$/", "10a010");   // => 0

d重復(fù)6次的寫法很不科學(xué),正則表達(dá)式肯定會(huì)有更方便的寫法,也就是量詞(quantifier)。量詞的通用形式是{m,n}(注意,,后面不能有空格),它限定之前的元素能夠出現(xiàn)的次數(shù),m是下限,n是上限。其他常見的量詞形式有:

量詞 說明
{n} 之前的元素必須出現(xiàn)n次
{m,n} 之前的元素最少出現(xiàn)m次,最多出現(xiàn)n次
{m,} 之前的元素最少出現(xiàn)m次,出現(xiàn)次數(shù)無上限
{0,n} 之前的元素可以不出現(xiàn),也可以出現(xiàn),最多出現(xiàn)n次
preg_match("/^d{6}$/", "100010");      // => 1

preg_match("/^d{4,6}$/", "123");       // => 0
preg_match("/^d{4,6}$/", "1234");      // => 1
preg_match("/^d{4,6}$/", "123456");    // => 1
preg_match("/^d{4,6}$/", "1234567");   // => 0
常用量詞

正則表達(dá)式還有三個(gè)常用的量詞,分別是+、?*

常用量詞 {m,n}等價(jià)形式 說明
* {0,} 可能出現(xiàn),也可能不出現(xiàn),出現(xiàn)次數(shù)沒有上限
+ {1,} 至少出現(xiàn)1次,出現(xiàn)次數(shù)沒有上限
? {0,1} 出現(xiàn)0次或1次

這三種量詞在實(shí)際中使用的非常多。

例如,匹配url的時(shí)候,有可能是http,也有可能是https,這個(gè)時(shí)候用?就很方便:

preg_match("/^https?://www.baidu.com/", "http://www.baidu.com");    // => 1
preg_match("/^https?://www.baidu.com/", "https://www.baidu.com");   // => 1

在匹配html的tag(如、

等),同時(shí),也不能匹配一個(gè)空的標(biāo)簽<>。
直接使用<[^/]+>/字符排除是不對(duì)的,因?yàn)橛行?biāo)簽的屬性中可能會(huì)含有/字符。例如。這里只是在開尖括號(hào)<之后的第一個(gè)字符和閉尖括號(hào)>之前的第一個(gè)字符不能為/。
然而<[^/][^>]*[^/]>也是不行的,因?yàn)樵?b><與>之間會(huì)至少匹配兩個(gè)字符,像
這樣的標(biāo)簽是無法匹配到的。這里就要用到環(huán)視了。

<(?!/).*+(?

上面的正則表達(dá)式中有兩個(gè)環(huán)視結(jié)構(gòu),一個(gè)在開尖括號(hào)<之后,表示在尖括號(hào)<后向右看看,右邊的第一個(gè)字符不能為/(正則表達(dá)式中進(jìn)行了轉(zhuǎn)義);另外一個(gè)在閉尖括號(hào)>之前,表示在閉尖括號(hào)>之前向左看看,左邊挨著的字符不能為/。

上面的正則表達(dá)式已經(jīng)解決了匹配html中開標(biāo)簽的主要問題,只是其中的.*?還需要優(yōu)化一下。需要解決的問題是:

有可能會(huì)有單引號(hào)"或雙引號(hào)",它們都得成對(duì)出現(xiàn)

單引號(hào)對(duì)或雙引號(hào)對(duì)之內(nèi)可以有>字符,但是它們的外面不能有>字符

利用正則表達(dá)式的選擇結(jié)構(gòu),可以寫出下面的表達(dá)式,用于完善上面的問題。

<(?!/)(?:"[^"]*"|"[^"]*"|[^"">])+(?

5.匹配模式

前面的內(nèi)容中已經(jīng)出現(xiàn)介過了單行模式、多行模式非貪婪模式。匹配模式是指匹配時(shí)使用的規(guī)則。常用的匹配模式還有不區(qū)分大小寫模式、注釋模式

在開始介紹具體的模式之前,先介紹php中模式的兩種具體實(shí)現(xiàn)/.../{modifier}...(?{modifier})...

.*/s(?s).*
模式修飾符 /.../{modifier} ...(?{modifier})...
示例 /
名稱(php手冊(cè)) 模式修飾符 模式內(nèi)修飾符
名稱(《正則指引》) 預(yù)定義常量 模式修飾符
作用范圍 整個(gè)正則表達(dá)式 不在分組(子表達(dá)式)中時(shí),對(duì)它后面的全部正則表達(dá)式起作用;如果在分組(子表達(dá)式)中,則對(duì)它分組中的剩余部分起作用。在沒有分組,且放在整個(gè)正則表達(dá)式最前面的時(shí)候相當(dāng)于/.../{modifier}
支持程度 支持所有模式修飾符 支持部分模式修飾符
其他編程語言 可能不支持 一般都支持
不區(qū)分大小寫模式

在html中是不區(qū)分大小寫的,例如、、的作用是一樣的。如果要從網(wǎng)頁中提取,不使用匹配模式的表達(dá)式應(yīng)該是這樣:

<[tT][dD]>

由于標(biāo)簽只有兩個(gè)字符,所以上面的寫法還可以接受。但是如果標(biāo)簽是

閱讀需要支付1元查看
<