PHP正則式PCRE的總結差很少就下邊這些了。參考 PCRE與perl的差別 。php
錨(^、$、\A、\Z/\z)正則表達式
^、$ 在多行模式(PCRE_MULTILINE)下構造非緊固模式,在單行模式(美圓符號可匹配字符串尾部的一個換行符)下可構造緊固模式;而\A、\Z / \z只用於構造緊固模式(\G表示在目標中首次匹配位置,還能夠與$offset參數一塊兒使用)。spa
斷言.net
一個斷言指定一個必須在特定位置匹配的條件,不會致使當前的匹配點發生改變,不會從目標字符串中消耗任何字符,所以也不會出如今結果中。一個斷言子組之前瞻斷言「(?=)」或「(?!)」、後瞻斷言「(?<=)」或「(?<!)」形式出現:code
(1)\b指單詞邊界(\b在字符類中表示退格backspace字符),\B指非單詞邊界。
(2)當字符串結束字符爲換行符時,\Z 會將其看作字符串結尾匹配, 而 \z 只匹配字符串結尾。
(3)前瞻斷言(?!foo)bar會查找到任意的barxxxxx而非foo跟隨bar的狀況。
(4)後瞻斷言的內容被嚴格限制爲只能用於匹配定長字符串,好比 (?<=bullock|donkey) 是容許的,可是 (?<!dogs?|cats?)、 (?<=ab(c|de)) 將會引起一個編譯期的錯誤。
(5)多個斷言(任意順序)能夠同時出現,如 (?<=\d{3})(?<!999)foo 匹配前面有三個數字但不是 」999」 的字符串 」foo」。
(6)斷言能夠以任意複雜度嵌套,好比 (?<=(?<!foo)bar)baz 匹配前面有 」bar」 可是 」bar」 前面沒有 」foo」 的 」baz」, 另外(?<=\d{3}…(?<!999))foo 匹配前面有三個數字字符緊跟 3 個不是 999 的任意字符的 」foo」。
(7)若是全部的斷言都包含一個捕獲子組,那麼爲了在整個模式中捕獲子組計數的目的,它們都會被計算在內;然而子字符串的捕獲僅能夠用於正面斷言,由於對於消極的斷言是沒有意義的。xml
內部選項(?)blog
若是一個選項在子組內部設置,僅僅改變子組中剩餘的部分,所以 (a(?i)b)c 僅僅匹配 」abc」 和 」aBc」 (假設沒有使用 PCRE_CASELESS 選項);但在同一個子模式中, 一個分支的內部選項設置會穿透到後面的其餘分支中去,好比 (a(?i)b|c) 匹配」ab」或「aB」或「c」或」C」(選項是在編譯期肯定下來的,在匹配 」C」 時第一個分支已被丟棄)。(?im) 設置代表多行大小寫不敏感匹配, 而(?im-sx) 設置了 PCRE_CASELESS,PCRE_MULTILINE, 可是同時取消了 PCRE_DOTALL 和 PCRE_EXTENDED。 若是一個字母即出如今 - 以前, 也出如今 - 以後,這個選項被取消設置。遞歸
模式修飾符內存
主要有i(PCRE_CASELESS)、m(PCRE_MULTILINE)、s(PCRE_DOTALL)、x(PCRE_EXTENDED)、A(PCRE_ANCHORED)、D(PCRE_DOLLAR_ENDONLY)、U(PCRE_UNGREEDY)等。模式修飾符中的空格、換行符會被忽略,其餘字符會致使錯誤。資源
子組/子模式與分支(|)
子組經過圓括號(其做用是局部化和捕獲子組,而「(?:)」不捕獲子組,「(?|)」使可多個分支複用一個後向引用編號)來分隔界定,而且它們能夠嵌套:
(1)cat(arcat|erpillar|)匹配 」cat」, 「cataract」, 「caterpillar」 中的一個。
(2)一次性子組(非捕獲子組)和後瞻斷言結合使用來指定在目標字符串末尾的有效匹配,好比^(?>.*)(?<=abcd)相對於^.*abcd$更爲高效。
(3)條件子組(非捕獲子組)型如(?(condition)yes-pattern)、(?(condition)yes-pattern|no-pattern),condition是數字(後向引用某個捕捉子組)或字串或斷言。
(\()?[^()]+(?(1)\))
改模式匹配一個沒有括號的或者閉合括號包裹的字符序列。
(4)命名子組(捕獲子組)形如 (?P<name>pattern)、(?<name>pattern)、(?’name’pattern),可經過(?P>name)、(?P&name)形式在模式中再次引用命名子組,但這種引用不可捕獲。
重複/量詞
* | 等價於 {0,} |
+ | 等價於 {1,} |
? | 等價於 {0,1} |
默認狀況下,量詞都是」貪婪」的,也就是說, 它們會在不致使模式匹配失敗的前提下,儘量多的匹配字符(直到最大容許的匹配次數),如對C代碼「/* first comment*/ not comment /*second comment*/」匹配註釋使用下列模式會匹配到整個字符串;
/\*.*\*/
然而,若是一個量詞緊跟着一個 ?(?起到模式反轉的做用,也就是說若是設置了 PCRE_UNGREEDY((?U)),模式將反轉爲貪婪;而若是量詞緊跟着一個+,表示任何狀況下都使用貪婪模式,所以 .*?abc 匹配 」aabc」, 可是 .*+abc 不匹配) 標記,它就會成爲懶惰(非貪婪)模式, 只作儘量少的匹配。 所以上述模式應該改爲這樣:
/\*.*?\*/
補充一下,在貪婪或懶惰模式下,都是在保證成功的條件下來控制匹配的重複次數最多或最少:
//$match = Array ( [0] => 214sfsbbb ) $patt = '/^\w*b$/'; preg_match($patt,'214sfsbbb',$match); //$match = Array ( [0] => 214sfsbbb ) $patt = '/^\w*?b$/'; preg_match($patt,'214sfsbbb',$match); //$match = Array ( [0] => 214sfsbbb ) $patt = '/^\w*b/'; preg_match($patt,'214sfsbbb',$match); //$match = Array ( [0] => 214sfsb ) $patt = '/^\w*?b/'; preg_match($patt,'214sfsbbb',$match); $subject = 'Aaaaaa Bbb'; $target = 0; //$subject = "0123456 7B8b9b10" $subject = preg_replace_callback_array( [ '/a?/i' => function ($match) use (&$target) { return $target++; }, ], $subject );
字符類與轉義字符
字符類\d、\D、 \s(任意空白字符,包括\r、\n、\t)、\S(任意非空白字符)、\w(任意單詞字符,包括字母、數字和_) 和 \W 也能夠出如今一個字符類中, 用以將其匹配的字符類加入到新的自定義字符類中。好比, [\dABCDEF] 匹配任意合法的 16 進制數, [^\W_] 匹配任何字母或數字但不匹配下劃線。\Q 和 \E 可忽略正則表達式元字符,
\w+\Q.$.\E$
該模式會匹配一個或多個單詞字符,緊接着一個點號,一個$,一個點號, 最後錨向字符串末尾;\K 能夠用於重置匹配,好比 foot\Kbar 匹配」footbar」,可是獲得的匹配結果是 」bar」。
註釋
模式中形如「(?# comments)」的部分表示註釋內容。若是設置了 PCRE_EXTENDED 選項, 一個字符類外部的未轉義的 # 字符就表明本行剩餘部分爲註釋。
遞歸模式(?R)
(?R) 提供了遞歸的這種特殊用法,如
\(((?>[^()]+)|(?R))*\)
該模式可匹配字串(ab(cd)ef)。
分隔符
分隔符可使任意非字母數字、非反斜線、非空白字符,如正斜線(/)、hash符號(#)、取反符號(~)等。
後向引用
(?1)、(?2)、(?P>name)、(?P&name)、(?P=name)、\一、\k<name>、\k’name’、\k{name}、\g{name}等形式能夠用於引用以前定義的子組。需注意,\n複用匹配結果,而(?n)、(?P>name)、(?P&name)複用模式。(a|(bc))\2 老是在匹配 」a」 開頭而不是 」bc」 開頭的字符串時失敗,故能夠換成(a|(bc))(?2)。對後向引用後有數字能夠空格分隔並使用x修飾符,或使用\g{n}這種格式(序列\1, \g1,\g{1}之間是同義關係),(foo)(bar)\g{-1} 能夠匹配字符串 」foobarbar」。子組內部後向引用本身(a\1)會失敗,但(a|b\1)*遇到aba會成功;也就是模式在第一次迭代的時候,必須可以保證不須要匹配後向引用。
PCRE不容許前瞻斷言的量詞修飾
(?!a){3}並不意味着接下來 3 個字符不是 a,而是斷言下一個字符不是 a 並進行了 3 次斷言。
//verify email address //$match: Array ( [0] => w12aqe_@124afasf.com [1] => 124afasf. ) $patt = '/^(?!_|-)(?>[\w\.-]+)@(?!-)(?>((?>[a-zA-Z0-9-]+)\.)+)[a-zA-Z]{2,46}$/'; preg_match($patt,'w12aqe_@124afasf.com',$match); //$match: Array ( [0] => Sunday [day] => Sunday [1] => Sunday ) $patt = '/(?<day>:(?i)saturday|sunday)/'; preg_match($patt,'Sunday',$match); //$match: Array ( [0] => Sunday [1] => Sun ) $patt = '/(?|(Sat)ur|(Sun))day/'; preg_match($patt,'Sunday',$match); //子組發生重複屢次匹配時,捕獲的是最新一次的值 //$match: Array ( [0] => (ab(cd)ef) [1] => ab(cd)ef [2] => ef ) $patt = '/\( ( ( (?>[^()]+) | (?R) )* ) \)/x'; preg_match($patt,'(ab(cd)ef)',$match); //命名子組可經過名稱或序號來再次引用 //$match: Array ( [0] => 23ab45cd56 [number] => 23 [1] => 23 ) $patt = '/^(?P<number>\d+)ab(?P>number)cd(?1)$/'; preg_match($patt,'23ab45cd56',$match); //下列模式至關於^.*abcd$ //$match: Array ( [0] => 23abcd ) $patt = '/^(?>.*)(?<=abcd)/'; preg_match($patt,'23abcd',$match); //下列模式用於XML去空及壓縮 $package = '<?xml version="1.0" encoding="UTF-8"?> <PARAM> <DBID>35</DBID> <SEQUENCE>atgtca</SEQUENCE> <MAXNS>10</MAXNS> <MINIDENTITIES>90</MINIDENTITIES> <MAXEVALUE>10</MAXEVALUE> <USERNAME>ad m in</USERNAME> <PASSWORD>111111</PASSWORD> <TYPE>P</TYPE> <RETURN_TYPE></RETURN_TYPE> </PARAM>';
// 去除空元素
$package = preg_replace('/<(\w+)[^>]*>\s*<\/\1>|<\w+[^>]*\/>/i', '', $package);
// XML壓縮
$package = preg_replace('/(?<=>)\s+(?=<\/?\w+>)/i', '', $package);
PCRE系統錯誤
// 打印最近的PCRE錯誤,非0值表示發生錯誤 var_dump(preg_last_error()); // preg_last_error() == 2時,可上調設置最大回溯解決,但不可無限上調該設置以避免消耗內存資源過大。默認 pcre.backtrack_limit = 1000000
ini_set('pcre.backtrack_limit', 100000000);