国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

正則表達式基本知識(php)

lunaticf / 2412人閱讀

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

這里的知識點基本上是《正則指引》的讀書筆記,只是每個知識點的示例代碼用php來實現。

1. 字符組

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

字符組的基本用法

[...]

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

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

為什么是[0-9],而不是[9-0]
因為-表示的范圍一般是根據字符對應的碼值(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進制
字符組簡記法(shorthands)

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

php中支持的字符組簡記:

d 所有的數字,即[0-9]

D 所有的非數字,與d互斥

w 所有的單詞字符(字符、數字、下劃線),即[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
元字符與轉義

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

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

仔細看上面第一個表達式和最后兩個表示式。這里要注意:

在php中,字符串既可以用單引號標注也可以用雙引號標注。兩者的主要區別在于,雙引號字符串可以插值,二單引號字符串不能;另外,雙引號字符串會處理字符串轉義,二單引號字符串不會

正則表達式是以字符串的方式提供的。在php中,雙引號字符串本身也有關于轉義的規定(如""" "" "等),因此"0-9""0-9"是等價的。

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

因此,在正則表達式中轉義要小心,在php中,使用單引號字符串來構建正則表達式會比雙引號字符串更簡單明了。

排除型字符組(Negated Character Class)

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

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

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

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

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

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

對于PCRE規范中的dws等字符組簡記法,POSIX中有類似的東西,叫做POSIX字符組。在ASCⅡ語言環境(locale)中,常見的POSIX字符組及其含義如下:

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

php中有專門處理POSIX正則的函數,但從5.3.0開始已經廢棄了。這里只是了解一下相關知識。

2. 量詞

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

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

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

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

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

量詞 說明
{n} 之前的元素必須出現n次
{m,n} 之前的元素最少出現m次,最多出現n次
{m,} 之前的元素最少出現m次,出現次數無上限
{0,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
常用量詞

正則表達式還有三個常用的量詞,分別是+?*

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

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

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

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

在匹配html的tag(如

等),同時,也不能匹配一個空的標簽<>
直接使用<[^/]+>/字符排除是不對的,因為有些標簽的屬性中可能會含有/字符。例如。這里只是在開尖括號<之后的第一個字符和閉尖括號>之前的第一個字符不能為/
然而<[^/][^>]*[^/]>也是不行的,因為在<>之間會至少匹配兩個字符,像
這樣的標簽是無法匹配到的。這里就要用到環視了。

<(?!/).*+(?

上面的正則表達式中有兩個環視結構,一個在開尖括號<之后,表示在尖括號<后向右看看,右邊的第一個字符不能為/(正則表達式中進行了轉義);另外一個在閉尖括號>之前,表示在閉尖括號>之前向左看看,左邊挨著的字符不能為/

上面的正則表達式已經解決了匹配html中開標簽的主要問題,只是其中的.*?還需要優化一下。需要解決的問題是:

有可能會有單引號"或雙引號",它們都得成對出現

單引號對或雙引號對之內可以有>字符,但是它們的外面不能有>字符

利用正則表達式的選擇結構,可以寫出下面的表達式,用于完善上面的問題。

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

5.匹配模式

前面的內容中已經出現介過了單行模式多行模式非貪婪模式匹配模式是指匹配時使用的規則。常用的匹配模式還有不區分大小寫模式注釋模式

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

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

在html中是不區分大小寫的,例如的作用是一樣的。如果要從網頁中提取,不使用匹配模式的表達式應該是這樣:

<[tT][dD]>

由于標簽只有兩個字符,所以上面的寫法還可以接受。但是如果標簽是

閱讀需要支付1元查看
<