模式文法 — 解說 Perl 相容Regex的文法

來源:互聯網
上載者:User
Differences From Perl PCRE 函數 PCRE Patterns PHP 手冊 模式文法

(No version information available, might only be in SVN)

模式文法 — 解說 Perl 相容Regex的文法 說明

PCRE 庫是一組用和 Perl 5 相同的文法和語義實現了Regex模式比對的函數,不過有少許區別(見下面)。當前 PCRE 的實現是與 Perl 5.005 相符的。 與 Perl 的區別

這裡談到的區別是就 Perl 5.005 來說的。 預設情況下,空白字元是 C 語言庫函數 isspace() 所能識別的任何字元,儘管有可能與別的字元類型表編譯在一起。通常 isspace() 匹配空格,換頁符,分行符號,斷行符號符,水平定位字元和垂直定位字元。Perl 5 不再將垂直定位字元包括在空白字元中了。事實上長久以來存在於 Perl 文檔中的逸出序列 \v 從未被識別過,不過該字元至少到 5.002 為止都被當成空白字元的。在 5.004 和 5.005 中 \s 不匹配此字元。 PCRE 不允許在向前斷言中使用重複的數量符。Perl 允許這樣,但可能不是你想象中的含義。例如,(?!a){3} 並不是斷言下面三個字元不是“a”,而是斷言下一個字元不是“a”三次。 捕獲出現在排除模式斷言中的子模式雖然被計數,但並未在位移向量中設定其條目。Perl 在匹配失敗前從此種模式中設定其數字變數,但只在排觸摸式斷言只包含一個分支時。 儘管目標字串中支援二進位的零字元,但不能出現在模式字串中,因為它被當作普通的 C 字串傳遞,以二進位零終止。逸出序列“\x00”可以在模式中用來表示二進位零。 不支援下列 Perl 逸出序列:\l,\u,\L,\U。事實上這些是由 Perl 的字串處理來實現的,並不是模式比對引擎的一部分。 不支援 Perl 的 \G 斷言,因為這和單個的模式比對無關。 很明顯,PCRE 不支援 (?{code}) 結構。 當部分模式重複的時候,有關 Perl 5.005_02 捕獲字串的設定有些古怪的地方。舉例說,用模式 /^(a(b)?)+$/ 去匹配 "aba" 會將 $2 設為 "b",但是用模式 /^(aa(bb)?)+$/ 去匹配 "aabbaa" 會使 $2 無值。然而,如果把模式改成 /^(aa(b(b))?)+$/,則 $2(和 $3)就有值了。在 Perl 5.004 中以上兩種情況下 $2 都會被賦值,在 PCRE 中也是 TRUE。如果以後 Perl 改了,PCRE 可能也會跟著改。 另一個未解決的矛盾是 Perl 5.005_02 中模式 /^(a)?(?(1)a|b)+$/ 能匹配上字串 "a",但是 PCRE 不會。然而,在 Perl 和 PCRE 中用 /^(a)?a/ 去匹配 "a" 會使 $1 沒有值。

PCRE 提供了一些對 Perl Regex機制的擴充: 儘管向後斷言必須匹配固定長度字串,但每個向後斷言的分支可以匹配不同長度的字串。Perl 5.005 要求所有分支的長度相同。 如果設定了 PCRE_DOLLAR_ENDONLY 而沒有設定 PCRE_MULTILINE,則 $ 元字元只匹配字串的最末尾。 如果設定了 PCRE_EXTRA,反斜線後面跟一個沒有特殊含義的字母會出錯。 如果設定了 PCRE_UNGREEDY,則重複的數量符的 greed 被反轉,即,預設時不是 greedy,但如果後面跟上一個問號就變成 greedy 了。

Regex詳解 介紹

下面說明 PCRE 所支援的Regex的文法和語義。Perl 文檔和很多其它書中也解說了Regex,有的書中有很多例子。Jeffrey Friedl 寫的“Mastering Regular Expressions”,由 O'Reilly 出版社發行(ISBN 1-56592-257-3),包含了大量細節。這裡的說明只是個參考文檔。

Regex是從左向右去匹配目標字串的一組模式。大多數字元在模式中表示它們自身並匹配目標中相應的字元。作為一個小例子,模式 The quick brown fox 匹配了目標字串中與其完全相同的一部分。 元字元

Regex的威力在於其能夠在模式中包含選擇和迴圈。它們通過使用元字元來編碼在模式中,元字元不代表其自身,它們用一些特殊的方式來解析。

有兩組不同的元字元:一種是模式中除了方括弧內都能被識別的,還有一種是在方括弧內被識別的。方括弧之外的元字元有這些: \ 有數種用途的通用轉義符 ^ 斷言目標的開頭(或在多行模式下行的開頭,即緊隨一分行符號之後) $ 斷言目標的結尾(或在多行模式下行的結尾,即緊隨一分行符號之前) . 匹配除了分行符號外的任意一個字元(預設情況下) [ 字元類定義開始 ] 字元類定義結束 | 開始一個多選一的分支 ( 子模式開始 ) 子模式結束 ? 擴充 ( 的含義,也是 0 或 1 數量限定符,以及數量限定符最小值 * 匹配 0 個或多個的數量限定符 + 匹配 1 個或多個的數量限定符 { 最少/最多數量限定開始 } 最少/最多數量限定結束

模式中方括弧內的部分稱為“字元類”。字元類中可用的元字元為: \ 通用逸出字元 ^ 排除字元類,但僅當其為第一個字元時有效 - 指出字元範圍 ] 結束字元類

以下說明了每一個元字元的用法。 反斜線(\)

反斜線字元有幾種用途。首先,如果其後跟著一個非字母數字字元,則取消該字元可能具有的任何特殊含義。此種將反斜線用作逸出字元的用法適用於無論是字元類之中還是之外。

例如,如果想匹配一個“*”字元,則在模式中用“\*”。這適用於無論下一個字元是否會被當作元字元來解釋,因此在非字母數字字元之前加上一個“\”來指明該字元就代表其本身總是安全的。尤其是,如果要匹配一個反斜線,用“\\”。

Note: 單引號或雙引號括起來的 PHP 字串中的反斜線有特殊含義。因此必須用Regex的 \\ 來匹配 \,而在 PHP 代碼中要用 "\\\\" 或 '\\\\'。

如果模式編譯時間加上了 PCRE_EXTENDED 選項,模式中的空白字元(字元類中以外的)以及字元類之外的“#”到分行符號之間的字元都被忽略。可以用轉義的反斜線將空白字元或者“#”字元包括到模式中去。

反斜線的第二種用途提供了一種在模式中以可見方式去編碼不可列印字元的方法。並沒有不可列印字元出現的限制,除了代表模式結束的二進位零以外。但用文字編輯器來準備模式的時候,通常用以下的逸出序列來表示那些二進位字元更容易一些:

\a alarm,即 BEL 字元(0x07) \cx "control-x",其中 x 是任一字元 \e escape(0x1B) \f 換頁符 formfeed(0x0C) \n 分行符號 newline(0x0A) \r 斷行符號符 carriage return(0x0D) \t 定位字元 tab(0x09) \xhh 十六進位代碼為 hh 的字元 \ddd 八進位代碼為 ddd 的字元,或 backreference

“\cx”的精確效果如下:如果“x”是小寫字母,則被轉換為大寫字母。接著字元中的第 6 位(0x40)被反轉。從而“\cz”成為 0x1A,但“\c{”成為 0x3B,而“\c;”成為 0x7B。

在“\x”之後最多再讀取兩個十六進位數字(其中的字母可以是大寫或小寫)。在 UTF-8 模式下,允許用“\x{...}”,花括弧中的內容是表示十六進位數位字串。原來的十六進位逸出序列 \xhh 如果其值大於 127 的話則匹配了一個雙位元組 UTF-8 字元。

在“\0”之後最多再讀取兩個八位元字。以上兩種情況下,如果少於兩個數字,則只使用已出現的。因此序列“\0\x\07”代表兩個二進位的零加一個 BEL 字元。如果是八位元字則確保在開始的零後面再提供兩個數字。

處理反斜線後面跟著一個不是 0 的數字比較複雜。在字元類之外,PCRE 以十進位數字讀取該數字及其後面的數字。如果數字小於 10,或者之前運算式中捕獲到至少該數位左圓括弧,則這個序列將被作為逆向引用。有關此如何運作的說明在後面,以及括弧內的子模式。

在字元類之中,或者如果十進位數字大於 9 並且之前沒有那麼多捕獲的子模式,PCRE 重新從反斜線開始讀取其後的最多三個八位元字,並以最低位的 8 個位元產生出一個單一位元組。任何其後的數字都代表自身。例如:

\040 另一種表示空格的方法 \40 同上,如果之前捕獲的子模式少於 40 個的話 \7 總是一個逆向引用 \11 可能是個逆向引用,或者是定位字元 tab \011 總是表示定位字元 tab \0113 表示定位字元 tab 後面跟著一個字元“3” \113 表示八進位代碼為 113 的字元(因為不能超過 99 個逆向引用) \377 表示一個所有的位元都是 1 的位元組 \81 要麼是一個逆向引用,要麼是一個二進位的零後面跟著兩個字元“8”和“1”

注意八進位值 100 或更大的值之前不能以零打頭,因為不會讀取(反斜線後)超過三個八位元字。

所有的定義了一個單一位元組的序列可以用於字元類之中或之外。此外,在字元類之中,序列“\b”被解釋為反斜線字元(0x08),而在字元類之外有不同含義(見下面)。

反斜線的第三個用法是指定通用字元類型:

\d 任一十進位數字 \D 任一非十進位數的字元 \s 任一空白字元 \S 任一非空白字元 \w 任一“字”的字元 \W 任一“非字”的字元

任何一個逸出序列將完整的字元組合分割成兩個分離的部分。任一給定的字元匹配一個且僅一個逸出序列。

“字”的字元是指任何一個字母或數字或底線,也就是說,任何可以是 Perl "word" 的字元。字母和數位定義由 PCRE 字元表控制,可能會根據指定地區的匹配而改變。舉例說,在 "fr" (French) 地區,某些編碼大於 128 的字元用來表示重音字母,這些字元能夠被 \w 所匹配。

這些字元類型序列可以出現在字元類之中和之外。每一個匹配相應類型中的一個字元。如果當前匹配點在目標字串的結尾,以上所有匹配都失敗,因為沒有字元可供匹配。

反斜線的第四個用法是某些簡單的斷言。斷言是指在一個匹配中的特定位置必須達到的條件,並不會消耗目標字串中的任何字元。子模式中更複雜的斷言的用法在下面描述。反斜線的斷言有:

\b 字分界線 \B 非字分界線 \A 目標的開頭(獨立於多行模式) \Z 目標的結尾或位於結尾的分行符號前(獨立於多行模式) \z 目標的結尾(獨立於多行模式) \G 目標中的第一個匹配位置

這些斷言可能不能出現在字元類中(但是注意 "\b" 有不同的含義,在字元類之中也就是反斜線字元)。

字邊界是目標字串中的一個位置,其當前字元和前一個字元不能同時匹配 \w 或者 \W(也就是其中一個匹配 \w 而另一個匹配 \W),或者是字串的開頭或結尾,假如第一個或最後一個字元匹配 \w 的話。

\A,\Z 和 \z 斷言與傳統的音調符和美元符(下面說明)的不同之處在於它們僅匹配目標字串的絕對開頭和結尾而不管設定了任何選項。它們不受 PCRE_NOTBOL 或 PCRE_NOTEOL 選項的影響。\Z 和 \z 的不同之處在於 \Z 匹配了作為字串最後一個字元的分行符號之前以及字串的結尾,而 \z 僅匹配字串的結尾。

\G 斷言僅在當前匹配位置是匹配開始那一點時為真,如 preg_match() 的 offset 參數指定那樣。當 offset 的值非零時這和 \A 不同。自 PHP 4.3.3 起可用。

\Q 和 \E 自 PHP 4.3.3 起可被用來在模式中忽略Regex匹配字元。例如:\w+\Q.$.\E$ 將匹配一個或多個可組成字的字元,其後接著的是字面上的 .$. 並且位於字串末尾。 Unicode 字元屬性

自 PHP 4.4.0 和 5.1.0 起,當選擇了 additional escape sequences to match generic character types are available UTF-8 模式時有三種更多的轉移序列可用: \p{xx} 具有 xx 屬性的一個字元 \P{xx} 沒有 xx 屬性的一個字元 \X 一個擴充 Unicode 序列

以上由 xx 所表示的屬性名稱限於 Unicode 通用類型屬性。每個字元具有一個此種屬性,由兩個縮寫字母指定。為和 Perl 相容,可以在左花括弧和屬性名稱中間加入一個上箭頭符號來表示排除屬性。例如 \p{^Lu} 就和 \P{Lu} 相同。

如果在 \p 或 \P 中只用了一個字母,則包括了所有該字母開頭的屬性。此情況下,如果不是排除的話,可以省略花括弧。下面例子中的兩項具有相同效果:

    \p{L}    \pL   
所支援的屬性代碼
C Other - 其它
Cc Control - 控制
Cf Format - 格式
Cn Unassigned - 無符號
Co Private use - 私人
Cs Surrogate - 代替
L Letter -字母
Ll Lower case letter - 小寫字母
Lm Modifier letter - 修正符字母
Lo Other letter - 其它字母
Lt Title case letter - 標題大寫字母
Lu Upper case letter - 大寫字母
M Mark - 標記
Mc Spacing mark - 空格標記
Me Enclosing mark - 環繞標記
Mn Non-spacing mark - 非空格標記
N Number - 數字
Nd Decimal number - 十進位數字
Nl Letter number - 字母數字
No Other number - 其它數字
P Punctuation - 標點符號
Pc Connector punctuation - 串連標點符
Pd Dash punctuation - 橫線標點符
Pe Close punctuation - 結束標點符
Pf Final punctuation - 最終標點符
Pi Initial punctuation - 起始標點符
Po Other punctuation - 其它標點符號
Ps Open punctuation - 開始標點符
S Symbol - 符號
Sc Currency symbol - 貨幣符號
Sk Modifier symbol - 修正符號
Sm Mathematical symbol - 算術符號
So Other symbol - 其它符號
Z Separator - 分隔字元
Zl Line separator - 行分隔字元
Zp Paragraph separator - 段落分隔字元
Zs Space separator - 空格分隔字元

PCRE 不支援擴充屬性例如 "Greek" 或 "InMusicalSymbols"。

指定不區分大小寫匹配不影響此類逸出序列。例如 \p{Lu} 總是僅和大寫字母匹配。

\X 轉移符匹配能組成擴充 Unicode 序列的任何數目的 Unicode 字元。\X 和 (?>\PM\pM*) 相同。

也就是,它匹配一個沒有“mark”屬性,後面跟著零或多個具有“mark”屬性的字元,並且將此序列看成原子組(見下)。典型的具有“mark”屬性的字母是影響到前面的字元的重音符。

用 Unicode 屬性來匹配字元並不快,因為 PCRE 不得不搜尋一個包含超過一萬五千字元資料的結構。這正是為什麼在 PCRE 中傳統的逸出序列例如 \d 和 \w 不使用 Unicode 屬性。 音調符(^)和美元符($)

在字元類之外,預設匹配模式下,音調符是一個僅在當前匹配點是目標字串的開頭時才為真的斷言。在字元類之中,音調符的含義完全不同(見下面)。

如果涉及到幾選一時音調符不需要是模式的第一個字元,但如果出現在某個分支中則應該是該選擇分支的第一個字元。如果所有的選擇分支都以音調符開頭,這就是說,如果模式限制為只匹配目標的開頭,那麼這是一個緊固模式。(也有其它結構可以使模式成為緊固的。)

美元符是一個僅在當前匹配點是目標字串的結尾或者當最後一個字元是分行符號時其前面的位置時為 TRUE 的斷言(預設情況下)。如果涉及到幾選一時美元符不需要是模式的最後一個字元,但應該是其出現的分支中的最後一個字元。美元符在字元類之中沒有特殊含義。

美元符的含義可被改變使其僅匹配字串的結尾,只要在編譯或匹配時設定了 PCRE_DOLLAR_ENDONLY 選項即可。這並不影響 \Z 斷言。

如果設定了 PCRE_MULTILINE 選項則音調符和美元符的含義被改變了。此種情況下,它們分別匹配緊接著內部 "\n" 字元的之後和之前,再加上目標字串的開頭和結尾。例如模式 /^abc$/ 在多行模式下匹配了目標字串 "def\nabc",但正常時不匹配。因此,由於所有分支都以 "^" 開頭而在單行模式下成為緊固的模式在多行模式下為非緊固的。如果設定了 PCRE_MULTILINE,則 PCRE_DOLLAR_ENDONLY 選項會被忽略。

注意 \A,\Z 和 \z 序列在兩種情況下都可以用來匹配目標的開頭和結尾,如果模式所有的分支都以 \A 開始則其總是緊固的,不論是否設定了 PCRE_MULTILINE。 句號(.)

在字元類之外,模式中的圓點可以匹配目標中的任何一個字元,包括不可列印字元,但不匹配分行符號(預設情況下)。如果設定了 PCRE_DOTALL 則圓點也會匹配分行符號。處理圓點與處理音調符和美元符是完全獨立的,唯一的聯絡就是它們都涉及到分行符號。圓點在字元類之中沒有特殊含義。

\C 可以用來匹配單一位元組。在 UTF-8 模式下這有意義,因為句號可以匹配由多個位元組組成的整個字元。 方括弧([])

左方括弧開始了一個字元類,右方括弧結束之。單獨一個右方括弧不是特殊字元。如果在字元類之中需要一個右方括弧,則其應該是字元類中的第一個字元(如果有音調符的話,則緊接音調符之後),或者用反斜線轉義。

字元類匹配目標中的一個字元,該字元必須是字元類定義的字元集中的一個;除非字元類中的第一個字元是音調符,此情況下目標字元必須不在字元類定義的字元集中。如果在字元類中需要音調符本身,則其必須不是第一個字元,或用反斜線轉義。

舉例說,字元類 [aeiou] 匹配了任何一個小寫母音字母,而 [^aeiou] 匹配了任何一個不是小寫母音字母的字元。注意音調符只是一個通過枚舉指定那些不在字元類之中的字元的符號。不是斷言:仍舊會消耗掉目標字串中的一個字元,如果當前位置在字串結尾的話則失敗。

當設定了不區分大小寫匹配時,字元類中的任何字母同時代表了其大小寫形式,因此舉例說,小寫 [aeiou] 同時匹配了 "A" 和 "a",小寫 [^aeiou] 不匹配 "A",但區分大小寫時則會匹配。

分行符號在字元類中不會特殊對待,不論 PCRE_DOTALL 或者 PCRE_MULTILINE 選項設定了什麼值。形如 [^a] 的字元類總是能夠和分行符號相匹配的。

減號(-)字元可以在字元類中指定一個字元範圍。例如,[d-m] 匹配了 d 和 m 之間的任何字元,包括兩者。如果字元類中需要減號本身,則必須用反斜線轉義或者放到一個不能被解釋為指定範圍的位置,典型的位置是字元類中的第一個或最後一個字元。

字面上的 "]" 不可能被當成字元範圍的結束。形如 [W-]46] 的模式會被解釋為包括兩個字元的字元類("W" and "-")後面跟著字串 "46]",因此其會匹配 "W46]" 或者 "-46]"。然而,如果將 "]" 用反斜線轉義,則會被當成範圍的結束來解釋。因此 [W-\]46] 會被解釋為一個字元類,包含有一個範圍以及兩個單獨的字元。八進位或十六進位表示的 "]" 也可以用來表示範圍的結束。

範圍是以 ASCII 比較順序來操作的。也可以用於用數字表示的字元,例如 [\000-\037]。在不區分大小寫匹配中如果範圍裡包括了字母,則同時匹配大小寫字母。例如 [W-c] 等價於 [][\^_`wxyzabc] 不區分大小寫地匹配。如果使用了 "fr" 地區的字元表,[\xc8-\xcb] 匹配了大小寫重音 E 字元。

字元類型 \d,\D,\s,\S,\w 和 \W 也可以出現於字元類中,並將其所能匹配的字元添加進字元類中。例如,[\dABCDEF] 匹配了任何十六進位數字。用音調符可以很方便地制定嚴格的字元集,例如 [^\W_] 匹配了任何字母或數字,但不匹配底線。

任何除了 \,-,^(位於開頭)以及結束的 ] 之外的非字母數字字元在字元類中都沒有特殊含義,但是將它們轉義也沒有壞處。 豎線(|)

豎線字元用來分隔多選一模式。例如,模式:

gilbert|sullivan
匹配了 "gilbert" 或者 "sullivan" 中的一個。可以有任意多個分支,也可以有空的分支(匹配Null 字元串)。匹配進程從左至右輪流嘗試每個分支,並使用第一個成功匹配的分支。如果分支在子模式(在下面定義)中,則“成功匹配”表示同時匹配了子模式中的分支以及主模式的其它部分。

內部選項設定

PCRE_CASELESS,PCRE_MULTILINE,PCRE_DOTALL,PCRE_EXTRA 和 PCRE_EXTENDED 的設定可以在模式內部通過包含在 "(?" 和 ")" 之間的 Perl 選項字母序列來改變。選項字母為:

內部選項字母
i 代表 PCRE_CASELESS
m 代表 PCRE_MULTILINE
s 代表 PCRE_DOTALL
x 代表 PCRE_EXTENDED
U 代表 PCRE_UNGREEDY
X 代表 PCRE_EXTRA

例如,(?im) 設定了不區分大小寫,多行匹配。也可以通過在字母前加上減號來取消這些選項。例如組合的選項 (?im-sx),設定了 PCRE_CASELESS 和 PCRE_MULTILINE,並取消了 PCRE_DOTALL 和 PCRE_EXTENDED。如果一個字母在減號之前與之後都出現了,則該選項被取消設定。

如果選項改變出現於頂層(即不在子模式的括弧中),則改變應用於其後的剩餘模式。因此 /ab(?i)c/ 只匹配 "abc" 和 and "abC"。此行為是自 PHP 4.3.3 起綁定的 PCRE 4.0 中被修改的。在此版本之前 /ab(?i)c/ 的執行與 /abc/i 相同(例如匹配 "ABC" 和 "aBc")。

如果選項改變出現於子模式中,則效果不同。這是 Perl 5.005 的行為的一個變化。子模式中的選項改變隻影響到子模式內部其後的部分,因此 (a(?i)b)c 將只匹配 "abc" 和 "aBc"(假定沒有使用 PCRE_CASELESS)。這意味著選項在模式的不同部位可以造成不同的設定。在一個分支中的改變可以傳遞到同一個子模式中後面的分支中,例如 (a(?i)b|c) 將匹配 "ab","aB","c" 和 "C",儘管在匹配 "C" 的時候第一個分支會在選項設定之前就被丟棄。這是因

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.