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'。
regex(3)
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.
袁乙鈞 <[email protected]>
2004.02.24
http://cmpp.linuxforum.net
本頁面中文版由中文 man
手冊頁計劃提供。
中文 man 手冊頁計劃:
https://github.com/man-pages-zh/manpages-zh