REGEX(7) | Miscellaneous Information Manual | REGEX(7) |
regex - POSIX 1003.2 正則表達式
正則表達式 (``RE''s), 在 POSIX 1003.2 中定義,包含兩種類型: 新式 REs (基本上指的是 egrep 使用的那些,1003.2 稱其爲 ``extended'' REs 也就是“擴展的REs”) 和舊式 REs (指的是 ed(1) 中的那些,1003.2 稱之爲 ``basic'' REs 也就是“基本的REs”). 舊式 REs 的存在僅僅是爲了向後和一些舊程序保持兼容;在最後將加以討論。 1003.2 對 RE 語法和語義的某些方面沒有做強制規定; `(!)' 記號標示了這些內容,它們可能不能完全移植到其他 1003.2 實現當中。
一個(新式的) RE 正則表達式是一個(!) 或多個非空(!) branches 分支,以 `|' 分隔。 它匹配任何匹配其中一個分支的符號串。
一個 branch 分支是一個(!) 或多個 pieces 片段連結而成。 符號串首先要匹配它的第一個片段,接下來剩餘部分再匹配第二個片段,以此類推。
一個 piece 片段是一個 atom 原子,其後可能包含一個(!) `*', `+', `?', 或者 bound 量詞。 一個原子加上 `*' 匹配零個或多個這個原子的匹配構成的序列。 一個原子加上 `+' 匹配一個或多個這個原子的匹配構成的序列。 一個原子加上 `?' 匹配零個或一個這個原子的匹配。
一個 bound 量詞是 `{' 後面跟一個無符號十進制整數,可能還會跟一個 `,', 可能還會再跟一個無符號十進制整數,然後以 `}' 結束。 整數的大小必須在 0 和 RE_DUP_MAX (255(!)) 之間(包含邊界值)。 如果給出了兩個數字,那麼第一個決不能比第二個大。 一個原子的量詞中如果只有一個數字而沒有逗號的話,就匹配 i 個這個原子的匹配構成的序列。 一個原子的量詞中如果只有一個數字並且有逗號的話,就匹配 i 個或多個這個原子的匹配構成的序列。 一個原子的量詞中如果包含兩個數字 i 和 j 的話,就匹配 i 到 j 個這個原子的匹配構成的序列。
一個原子是一個包含在 `()' 中的正則表達式 (這將匹配這個正則表達式匹配的符號串), 一個空的 `()' (匹配空串), 一個 bracket expression (方括號表達式,參見下面), `.' (匹配任何字符), `^' (匹配行首的空字符串), `$' (匹配行尾的空字符串), 一個 `\' 加上下列字符之一 `^.[$()|*+?{\' (匹配這個字符,忽略它的任何特殊意義), 一個 `\' (加上任何其他字符(!) 匹配那個字符,忽略它的任何特殊意義,就好像 `\' 不存在(!)), 或者是一個字符,沒有特殊意義 (匹配它本身)。 一個 `{' 後面是一個非數字的字符時,是一個普通的字符而不是量詞的開始(!)。 以 `\' 來結束一個 RE 是非法的。
一個 bracket expression 方括號表達式是一個字符的列表,包含在 `[]' 當中。 它一般匹配列表中的任何一個字符 (有特殊情況)。 如果這個列表以 `^' 開始,它將匹配 不在 列表中的任何字符 (下面還會講到特殊情況)。 如果列表中的兩個字符以 `-' 分隔,可以表示字母表中這兩個字符之間(包括這兩個字符)所有的字符。 例如,ASCII 字符表中 `[0-9]' 匹配任何數字。 不能(!) 用一個字符作爲定義兩個字符範圍的端點,就像這樣 `a-c-e'。 字符範圍是與字母表順序相關的,可移植的程序不應使用它們。
要在列表中包含一個字面的(沒有特殊含義的) `]',可以把它放在首位(後面可能要加上一個`^')。 要在列表中包含一個字面的 `-',可以把它放在首位或末尾,或者讓它作爲一個字符範圍的末端點。 要以一個字面的 `-' 作爲字符範圍的起始,可以將它放在 `[.' 和 `.]' 當中, 使得它成爲一個 collating element (歸併元素,參見下面)。 特殊情況除了這些,還有使用 `[' 的組合(參見下一段)。所有其他特殊字符,包括 `\' 在內,在方括號表達式中都失去了它們的特殊含義。
方括號表達式中,一個包含在 `[.' 和 `.]' 中的歸併元素 (collating element,一個字符,一個視爲一體的字符序列, 或者一個代表着上述兩類的歸併序列名稱) 代表着這個歸併元素所包含的字符序列。 這個序列被視爲方括號表達式的一個元素。 因此一個包含着多字符歸併元素的方括號表達式可以匹配多於一個的字符。 例如,如果這個歸併序列包含一個歸併元素 `ch',那麼 正則表達式 `[[.ch.]]'*c' 可以匹配 `chchcc' 的前五個字符。
方括號表達式中,一個包含在 `[=' 和 `=]' 中的歸併元素是一個等價類,代表着 等價於它的所有歸併元素 (也包括它自身)包含的字符的序列。 (如果沒有其他等價的歸併元素,就把它與括號分隔符是 `[.' 和 `.]' 時同樣看待。) 例如,如果 o 和 ^ 是一個等價類的成員,那麼 `[[=o=]]',`[[=^=]]' 還有 `[o^]' 都是同義詞。 一個等價類不能(!) 是一個字符範圍的末端點。
方括號表達式中,包含在 `[:' 和 `:]' 中的一個 character class(字符類) 代表着這個 字符類中的所有字符的列表。 標準的字符類名稱是:
alnum digit punct alpha graph space blank lower upper cntrl print xdigit
它們代表着 wctype(3) 定義的字符類。 一個 locale(語言環境) 可能會提供其他字符類。 一個字符類不能用作一個字符範圍的末端點。
方括號表達式還有兩種特殊的情況(!) : 方括號表達式 `[[:<:]]' 和 `[[:>:]]' 分別匹配一個詞的開始和結尾的空字符串。 一個 word (詞)是一個 word character (成詞字符) 的序列,並且前後都沒有成詞字符。 一個 word character (成詞字符) 是一個 alnum 字符 (在 wctype(3) 中有定義) 或者是一個下劃線。 這是一個擴展,與 POSIX 1003.2 兼容但沒有寫入正文,在需要移植到其他系統中的軟件中應當小心使用。
如果一個 RE 可以匹配一個字符串的多個不同的字串時,RE 選擇匹配最前面的一個。 如果這個 RE 匹配的子串有相同的起始點,RE 選擇匹配最長的一個。 子表達式也匹配最長的字串,使得整個匹配的字串最長,RE 中前面 的子表達式比後面的子表達式優先級高。 注意高級的子表達式比組成它的子表達式優先級要高。
匹配長度以字符來計算,而不是歸併元素。 空字符串被認爲比沒有匹配要長。例如,`bb*' 匹配 `abbbc' 的中間三個字符; `(wee|week)(knights|nights)' 匹配 `weeknights' 的全部十個字符; `(.*).*' 匹配 `abc',其中括號中的子表達式匹配所有這三個字符; `(a*)*' 來和 `bc' 匹配時,括號中的子表達式和整個 RE 都匹配空字符串。
如果指定了 case-indepentent 忽略大小寫的匹配,效果是字母表中的大小寫區別似乎都消失了。 如果一個字母可能以兩種情況出現,假如它出現在方括號表達式之外,實際上被替換成了一個包含 所有情況的方括號表達式,例如 `x' 成爲了 `[xX]';如果它出現在方括號表達式之內, 那麼它的所有形式都被加入到這個方括號表達式之內,因此例如 `[x]' 等同於 `[xX]',還有 `[^x]' 成爲了 `[^xX]'。
對 RE 的長度沒有強制的限制。需要可移植的程序不應當使用長於256字節的正則表達式, 因爲特定的實現可以不接受這種 RE,但是仍然是 POSIX 兼容的。
過時的 (``basic'') 正則表達式在很多地方有不同之處。`|',`+' 和 `?' 是普通的字符, 並且沒有和它們等價的功能。量詞的分隔符是 `\{' 和 `\}',`{' 和 `}' 本身是普通的字符。 嵌套的子表達式使用的括號是 `\(' 和 `\)',`(' 和 `)' 本身是普通的字符。 `^' 是一個普通的字符,除非是 RE 的第一個字符,或者(!) 一個括號中的子表達式的第一個字符。 `$' 是一個普通的字符,除非是 RE 的最後一個字符,或者(!) 一個括號中的子表達式的最後一個字符。 `*' 是一個普通的字符,如果它出現在 RE 的開始,或者一個括號中的子表達式的開始(其後一般是一個 `^')。 最後,還有一類 atom 原子,一個 back reference(向後引用):`\' 其後跟一個非零十進制整數 d, 匹配與第 d 個括號中的子表達式的匹配相同的內容(子表達式的編號是根據它們的左括號而來,從左到右)。 因此(例如),`\([bc]\)\1' 匹配 `bb' 或 `cc' 但是不匹配 `bc'。
POSIX 1003.2, section 2.8 (Regular Expression Notation).
同時使用兩種 REs 是不明智的。
目前的 1003.2 規約稱,如果右括號 `)' 沒有對應的 `(' 那麼視爲普通字符;這個規定是一個筆誤,將來會改正。 避免使用它。
向後引用是糟糕的設計,是高效的實現中要面對的主要問題。 另外還會產生晦澀的語法 (?`a\(\(b\)*\2\)*d' 可以匹配 `abbbd' 嗎?)。 避免使用它們。
1003.2 對於忽略大小寫的匹配的規定也不明確。 上面給出的定義 ``one case implies all cases'' 是當前各實現者的共識,被當作正確的語法。
詞邊界的語法醜陋得讓人難以接受。
This page was taken from Henry Spencer's regex package.
袁乙鈞 <bbbush@163.com>
2004.02.24
http://cmpp.linuxforum.net
本頁面中文版由中文
man 手冊頁計劃提供。
中文 man
手冊頁計劃:https://github.com/man-pages-zh/manpages-zh
1994-02-07 |