9.6. 模式匹配

PostgreSQL 提供了三種實現模式匹配 的方法:SQL LIKE 操作符,更近一些的 SQL99 SIMILAR TO 操作符, 和POSIX-風格正則表達式. 另外還有一個模式匹配函數 substring 可以用, 可以使用 SQL99 風格的或者 POSIX 風格的正則表達式。

提示: 如果你的模式匹配的要求比這些還多,或者想寫一些模式驅動的 替換和轉換,請考慮用 Perl 或 Tcl 寫一個用戶定義函數.

9.6.1. LIKE

string LIKE pattern [ ESCAPE escape-character ]
string NOT LIKE pattern [ ESCAPE escape-character ]

每個 pattern 定義一個字串的集合. 如果該 string 包含在 pattern 代表的字串集合裡,那麼 LIKE 表達式返回真. (和我們想象的一樣,如果 LIKE 返回真,那麼 NOT LIKE 表達式返回假, 反之亦然。一個等效的表達式是 NOT (string LIKE pattern).)

如果 pattern 不包含百分號 或者下劃線,那麼該模式只代表它本身; 這時候 LIKE 的行為就象等號操作符. 在 pattern 裡的下劃線 (_)代表(匹配)任何單個字符; 而一個百分號(%)匹配任何零或更多 字符長的字串.

下面是一些例子︰

'abc' LIKE 'abc'    true
'abc' LIKE 'a%'     true
'abc' LIKE '_b_'    true
'abc' LIKE 'c'      false

LIKE 模式匹配總是覆蓋整個字串. 要匹配在字串內部任何位置的模式,該模式必須以百分號開頭和結尾.

要匹配文本的下劃線或者百分號,而不是匹配其它字符, 在pattern 裡相應的字符必須 前導逃逸字符.缺省的逃逸字符是反斜扛,但是你可以用 ESCAPE 子句指定一個. 要匹配逃逸字符本身,寫兩個逃逸字符.

請注意反斜扛在字串文本裡已經有特殊含義了,所以如果你寫一個 包含反斜扛的模式常量,那你就要在 SQL 語句裡寫兩個反斜扛. 因此,寫一個匹配單個反斜扛的模式實際上要在語句裡寫四個反斜扛. 你可以通過用 ESCAPE 選擇一個不同的逃逸字符 來避免這樣;這樣反斜扛就不再是 LIKE 的特殊字符了. 但仍然是字符文本分析器的特殊字符,所以你還是需要兩個反斜扛.)

我們也可以通過寫成 ESCAPE '' 的方式 有效地關閉逃逸機制,這時,我們就不能關閉下劃線和百分號的特殊含義.

關鍵字 ILIKE 可以用于替換 LIKE, 令該匹配就當前的區域設置是大小寫無關的. 這個特性不是 SQL 標準,是 PostgreSQL 擴展.

操作符 ~~ 等效于 LIKE, 而 ~~* 對應 ILIKE. 還有 !~~!~~* 操作符 分別代表 NOT LIKENOT ILIKE.所有這些操作符都是 PostgreSQL 特有的.

9.6.2. SIMILAR TOSQL99 正則表達式

string SIMILAR TO pattern [ESCAPE escape-character]
string NOT SIMILAR TO pattern [ESCAPE escape-character]

SIMILAR TO 根據自己的模式是否匹配給定字串而 返回真或者假。它和 LIKE 非常類似,只不過它 使用 SQL99 定義的正則表達式理解模式。 SQL99 的正則表達式是在 LIKE 表示法和普通的正則表達式表示法之間古怪的交叉。

類似 LIKESIMILAR TO 操作符只有在它的模式匹配整個字串的時候才能成功;這一點和普通的 正則表達式的習慣不同,在普通的正則表達式裡,模式匹配字串的任意 部分。 和 LIKE 類似的地方還有,SIMILAR TO 使用 _% 作為分別代表任意字串和任意字串字符 的通配符。(這些和 POSIX 正則表達式裡的 ..* 兼容)

除了這些從 LIKE 借用的功能之外, SIMILAR TO 支持下面這些從 POSIX 正則表達式借用的 模式匹配元字符:

請注意沒有提供範圍重復(?{...}), 盡管它們在 POSIX 裡有。同時,點(.)不是元字符。

LIKE 一樣,反斜槓關閉所有這些元字符的特殊含義; 當然我們也可以用 ESCAPE 聲明另外一個逃逸字符。

一些例子:

'abc' SIMILAR TO 'abc'      true
'abc' SIMILAR TO 'a'	false
'abc' SIMILAR TO '%(b|d)%'  true
'abc' SIMILAR TO '(b|c)%'   false

帶三個參數的substringsubstring(string from pattern for escape-character), 提供了一個從字串中抽取一個匹配SQL99正則表達式模式的子字串的函數。 和SIMILAR TO一樣,聲明的模式必須匹配整個數據串,否則函數失效並 返回 NULL。為了標識在成功的時候應該返回的模式部分,模式 必須出現後跟雙引號(")的兩個逃逸字符。匹配這兩個標記 之間的模式的字串將被返回。

一些例子:

substring('foobar' from '%#"o_b#"%' FOR '#')   oob
substring('foobar' from '#"o_b#"%' FOR '#')    NULL

9.6.3. POSIX 正則表達式

Table 9-11 列出了所有可用的 用于 POSIX 正則表達式的操作符。

Table 9-11. 正則表達式匹配操作符

操作符描述例子
~ 匹配正則表達式,大小寫相關'thomas' ~ '.*thomas.*'
~* 匹配正則表達式,大小寫無關'thomas' ~* '.*Thomas.*'
!~ 不匹配正則表達式,大小寫相關'thomas' !~ '.*Thomas.*'
!~* 不匹配正則表達式,大小寫無關'thomas' !~* '.*vadim.*'

POSIX 正則表達式提供了比 LIKESIMILAR TO 操作符 更強大的模式匹配的方法.許多 Unix 工具,比如 egrepsed,或 awk 使用一種與我們這裡描述的類似的模式匹配語言.

正則表達式是一個字符序列,它是定義一個字串集合 (一個正則集合)的縮寫. 如果一個字串是正則表達式描述的正則集合中的一員時, 我們就說這個字串匹配該正則表達式. 和 LIKE 一樣,模式字符準確地匹配字串字符, 除非在正則表達式語言裡有特殊字符 --- 不過正則表達式用的 特殊字符和 LIKE 用的不同. 和 LIKE 不一樣的是,正則表達式 可以匹配字串裡的任何位置,除非該正則表達式明確地掛接在字串 的開頭或者結尾.

一些例子:

'abc' ~ 'abc'    true
'abc' ~ '^a'     true
'abc' ~ '(b|d)'  true
'abc' ~ '^(b|c)' false

帶兩個參數的substringsubstring(string from pattern),提供了從字串中抽取一個匹配 POSIX 正則表達式模式的 子字串的方法。如果沒有匹配它返回 NULL,否則就是文本中匹配模式的那部分。 但是如果該模式包含任何圓括弧,那麼將返回匹配第一對子表達式(對應第一個左圓括弧的) 的文本。如果你想在表達式裡使用圓括弧,那麼你總可以在最外圍放上一對兒圓括弧 來避免出現這個問題。又見下面描述的非捕獲性圓括弧。

一些例子:

substring('foobar' from 'o.b')     oob
substring('foobar' from 'o(.)b')   o

PostgreSQL 的正則表達式是使用 Henry Spencer 寫的一個包來實現的。下面的正則表達式的大部分描述都是從他的手冊頁裡面 逐字拷貝過來的。

9.6.3.1. 正則表達式

正則表達式("RE"),在POSIX1003.2 中定義, 它有兩種形式:擴展的RE或者是ERE (基本上就是那些在 egrep 裡的), "基本"RE或者是BRE (基本上就是那些在 ed裡的)。 PostgreSQL 兩種形式都實現了,並且還做了一些POSIX裡面沒有的, 但是因為在類似 Perl 或者 Tcl 這樣的語言中得到廣泛應用的一些擴展。 使用了那些非POSIX擴展的 RE高級 RE, 或者我們文檔裡說的 ARE。ARE 幾乎完全是 ERE 的超集,但是 BRE 有幾個符號上的不兼容(以及更多的限制)。我們首先描述 ARE 和 ERE 形式, 描述那些只適用于 ARE 的特性,然後描述 BRE 的區別是什麼。

注意: 我們可以通過設置運行時參數 regex_flavor (在 Section 16.4 裡面描述)來選擇 PostgreSQL 接受的正則表達式的形式。 通常的設置是advanced(高級),但是我們可以選擇 extended 和 7.4 以前的PostgreSQL版本做到最大的向下兼容。

(現代)的 RE 是一個或多個非空的 分支, 由 | 分隔.它匹配任何匹配其中一個分支的東西.

一個分支是一個或多個有修飾的原子或者約束 連接而成.一個原子匹配第一個,然後後面的原子匹配第二個, 以此類推.

一個有修飾的原子是一個原子, 後面可能跟著一個量詞。沒有量詞的時候,它匹配一個原子, 有量詞的時候,它可以匹配若幹個原子。原子可以是在 Table 9-12裡面顯示的任何可能。 可能的量詞和他們的含義在 Table 9-13 裡顯示。

一個 constraint 匹配一個空字串,但只是在滿足特定條件下 才匹配。約束可以在能夠使用原子的地方使用,只是她不能跟著量詞。最簡單 的原子在 Table 9-14 裡顯示; 更多的約束稍後描述。

Table 9-12. 正則表達式原子

原子描述
(re) (這裡的 re 是任何正則表達式) 匹配一個對 re 的匹配,有可報告的匹配信息
(?:re) 同上,但是匹配不會被報告 (一個"不捕獲"圓括弧) (只在 ARE 中有)
. 匹配任意單個字符
[chars] 一個 方括弧表達式, 匹配任意的字符(參閱 Section 9.6.3.2 獲取更多細節)
\k (這裡的 k 是非字母數字字符) 匹配一個當作普通字符看待的特定字符, 比如,\\ 匹配一個反斜槓
\c 這裡的 c 是一個字母數字 (可能跟著其它字符),它是一個逃逸, 參閱 Section 9.6.3.3(僅存在于 ARE; 在 ERE 和 BRE 中,它匹配 c
{ 如果後面跟著一個字符,而不是數字, 那麼就匹配左花括弧{;如果跟著一個數字, 那麼它是範圍的開始(見下面)
x 這裡的 x 是一個沒有其它特征的單個字符, 則匹配該字符

RE 不能以 \ 結尾。

注意: 要記住反斜槓(\)在 PostgreSQL 字串文本中已經有特殊含義了。 要寫一個包含反斜槓的模式,你必須在語句裡寫兩個反斜槓。

Table 9-13. 正則表達式量詞

量詞匹配
* 一個匹配 0 或者更多個原子的序列
+ 一個匹配 1 或者更多個原子的序列
? 一個匹配 0 個或者 1 個原子的序列
{m} 一個正好匹配 m 個原子的序列
{m,} 一個匹配m 個或者更多原子的序列
{m,n} 一個匹配 mn 個(包含兩端) 原子的序列;m 不能比 n
*? * 的非貪婪模式
+? + 的非貪婪模式
?? ? 的非貪婪模式
{m}? {m} 的非貪婪模式
{m,}? {m,} 的非貪婪模式
{m,n}? {m,n} 的非貪婪模式

{...} 的形式被稱作範圍。 一個範圍內的數字 mn 都是無符號十進制整數, 允許的數值從 0 到 255(閉區間)。

非貪婪的量詞(只在 ARE 中可用)匹配對應的正常 (貪婪)模式,區別是它尋找最少的匹配,而不是最多的匹配。 參閱 Section 9.6.3.5 獲取細節。

注意: 一個量詞不能緊跟在另外一個量詞後面。量詞不能是表達式或者子表達式的開頭, 也不能跟在 ^ 或者 | 後面。

Table 9-14. 正則表達式約束

約束描述
^ 匹配字串的開頭
$ 匹配字串的結尾
(?=re) 正前瞻 匹配任何匹配 re 的 子字串起始點(只在 ARE 中有)
(?!re) 負前瞻 匹配任何不匹配 re 的子字串的起始點。(只在 ARE 中有)

前瞻約束不能包含後引用 (參閱 Section 9.6.3.3),並且在裡面的所有圓括弧 都被認為是不捕獲的。

9.6.3.2. 方括弧表達式

方括弧表達式是一個包圍在 [] 裡的字符列表.它通常匹配任意單個 列表中的字符(又見下文). 如果列表以 ^ 開頭,它匹配 任意單個(又見下文)不在該列表中的字符. 如果該列表中兩個字符用-隔開, 那它就是那兩個字符(包括在內)之間的所有字符範圍的縮寫, 比如,在 ASCII[0-9] 包含任何十進制數字. 兩個範圍共享一個終點是非法的,比如, a-c-e.這個範圍與字符集關系密切, 可移植的程序不應該依靠它們.

想在列表中包含文本 ],可以讓它做 列表的首字符(可能會在一個 ^ 後面). 想在列表中包含文本 -,可以讓它做 列表的首字符或者末字符,或者一個範圍的第二個終點. 想在列表中把文本-當做範圍的起點, 把它用 [..] 包圍起來,這樣它就成為一個集合元素(見下文). 除了這些字符本身,和一些用 [ 的組合(見下段),以及逃逸(只在 ARE 中有效)以外,所有其它特殊字符 在方括弧表達式裡都失去它們的特殊含義. 特別是,在 ERE 和 BRE 規則下 \ 不是特殊的, 但在 ARE 裡,它是特殊的(還是引入一個逃逸)。

在一個方括弧表達式裡,一個集合元素(一個字符,一個當做 一個字符的多字符序列,或者一個表示上面兩種情況的集合序列) 包含在 [..] 裡面的時候表示該集合元素的字符序列.該序列是該方括弧列表 的一個元素.因此一個包含多字符集合元素的方括弧表達式就 可以匹配多于一個字符,比如,如果集合序列包含一個 ch 集合元素, 那麼 RE [[.ch.]]*c 匹配 chchcc 的頭五個字符. (譯注:其實把 [. 和 .] 括起來的當一個字符看就行了.)

注意: PostgreSQL 目前沒有多字符集合元素。這些信息描述了將來可能有的行為。

在方括弧表達式裡,在[==] 裡包圍的集合元素是一個等效表, 代表等于這裡所有集合元素的字符序列,包括它本身. (如果沒有其它等效集合元素,那麼就好象封裝元素是 [..].) 比如,如果 o^ 是一個等效表的成員,那麼 [[=o=]][[=^=]],和 [o^] 都是同義的.一個等效表不能是一個範圍的 端點.

在方括弧表達式裡,在 [::] 裡面封裝的字符表名字代表 屬于該表的所有字符的列表. 標準的字符表名字是:alnumalphablankcntrldigitgraphlowerprintpunctspaceupperxdigit. 它們代表在 ctype 裡定義的字符表. 本地化設置可能會提供其他的表.字符表不能用做一個範圍的端點.

在方括弧表達式裡有兩個特例:方括弧表達式 [[:<:]][[:>:]] 是約束,分別匹配一個單詞開頭和結束的空串. 單詞定義為一個單詞字符序列,前面和後面都沒有其它單詞字符. 單詞字符是一個字母數字(和 ctype 裡定義的一樣) 或者一個下劃線.這是一個擴展,兼容POSIX1003.2, 但那裡面並沒有說明, 而且在準備移植到其他系統裡去的軟件裡一定要小心使用. 通常下面描述的約束逃逸更好些(他們並非更標準,但是肯定更容易敲入)。

9.6.3.3. 正則表達式逃逸

逃逸是以 \ 開頭,後面跟著一個字母數字字符得特殊序列。 逃逸有好幾種變體:字符項,表縮寫,約束逃逸,以及後引用。在 ARE 裡, 如果一個 \ 後面跟著一個字母數字,但是並未組成一個合法的逃逸, 那麼它是非法的。在 ERE 裡則沒有逃逸:在方括弧表達式之外,一個跟著字母數字字符 的 \ 只是表示該字符是一個普通的字符,而在一個方括弧表達式裡, \ 是一個普通的字符。(後者實際上是 ERE 和 ARE 之間的不兼容。)

字符項逃逸用于方便我們聲明RE裡那些不可打印的字符。 它們在 Table 9-15 裡列出。

表縮寫逃逸用來提供一些常用的字符表縮寫。 他們在 Table 9-16 裡顯示。

約束逃逸是一個約束,如果滿足特定的條件, 它匹配該空字串。它們在 Table 9-17 裡顯示。

後引用\n)匹配數字 n 指定的前面的圓括弧子表達式匹配的同一個字串 (參閱 Table 9-18)。比如, ([bc])\1匹配bb或者cc, 但是不匹配bc或者cb。RE裡子表達式必須完全在後引用前面。 非捕獲圓括弧並不定義子表達式。

注意: 請注意,如果把模式當作一個 SQL 字串常量輸入,那麼逃逸前導的 \ 需要成倍地寫。

Table 9-15. 正則表達式字符項逃逸

逃逸描述
\a 警笛(鈴聲)字符,和 C 裡一樣
\b 退格,和 C 裡一樣
\B \ 的同義詞,用于減少反斜槓加倍的需要
\cX (這裡 X 是任意字符)字符的 低 5 位和 X 裡的相同,其它位都是 0
\e 集合序列名字是 ESC 的字符, 如果不是,則是八進制值為 033 的字符
\f 進紙,和 C 裡一樣
\n 新行,和 C 裡一樣
\r 回車,和 C 裡一樣
\t 水平制表符,和 C 裡一樣
\uwxyz (這裡的 wxyz 和恰好四位十六進制位) 本機字節序的 Unicode 字符 U+wxyz
\Ustuvwxyz (這裡的 stuvwxyz 是恰好八位十六進制位) 為那種假想中的 Unicode 32 位擴展保留的
\v 垂直制表符,和 C 裡一樣
\xhhh (這裡 hhh 是一個十六進制序列) 十六進制值為 0xhhh 的字符 (不管用了幾個十六進制位,都是一個字符)
\0 值為 0 的字符
\xy (這裡的 xy 是恰好兩個八進制位, 並且不是一個 後引用)八進制值為 0xy 的字符
\xyz (這裡的 xyz 是恰好三位八進制位, 並且不是一個 後引用) 八進制值為 0xy的字符

十六進制位是 0-9a-f,和 A-F。八進制位是 0-7

字符項逃逸總是被當作普通字符。比如,\135 是 ASCII 中的 ], 但 \135 並不終止一個方括弧表達式。

Table 9-16. 正則表達式表縮寫逃逸

逃逸描述
\d [[:digit:]]
\s [[:space:]]
\w [[:alnum:]_] (注意,這裡是包含下劃線的)
\D [^[:digit:]]
\S [^[:space:]]
\W [^[:alnum:]_] (注意這裡是包含下劃線的)

在方括弧表達式裡,\d\s, 和 \w 會失去他們的外層方括弧,而 \D\S, 和 \W 是非法的。(也就是說,比如 [a-c\d] 等效于 [a-c[:digit:]]。同樣 [a-c\D],它原來等效于 [a-c^[:digit:]]的,也是非法的。)

Table 9-17. 正則表達式約束逃逸

逃逸描述
\A 只匹配字串開頭,(參閱 Section 9.6.3.5 獲取它和 ^ 區別的信息)
\m 只匹配一個詞的開頭
\M 只匹配一個詞的結尾
\y 只匹配一個詞的開頭或者結尾
\Y 只匹配那些既不是詞的開頭也不是詞的結尾的點
\Z 只匹配一個字串的結尾 (參閱 Section 9.6.3.5 獲取它和$區別的信息)

一個詞的定義是上面 [[:<:]][[:>:]] 的聲明。在方括弧表達式裡,約束逃逸是非法的。

Table 9-18. 正則表達式後引用

逃逸描述
\m (這裡的 m 是一個非零十進制位) 一個指向第 m 個子表達式的後引用
\mnn (這裡的 m 是一個非零十進制位,而 nn 是更多的十進制位,並且十進制數值 mnn 不能大于到這個位置為止的閉合捕獲圓括弧的個數) 一個指向第 mnn 個子表達式的後引用

注意: 在八進制字符項逃逸和後引用之間有一個歷史繼承的歧義存在,這個歧義是 通過啟發分析解決的,像上面描述地那樣。前導零總是表示這是一個八進制逃逸。 而單個非零數字,如果沒有跟著任何其它數字,那麼總是認為是後引用。 一個多數據位的非零開頭的序列也認為是後引用──只要它在合適的子表達式後面 (也就是說。數值在後引用的合法範圍那),否則就認為是一個八進制。

9.6.3.4. 正則表達式元語法

除了上面描述地主要語法之外,還有幾種特殊形式和雜項語法。

通常,RE 的風味由 regex_flavor 決定。但是,這個環境變量 可以被一個指示器前綴覆蓋。如果任何類型的 RE 以***: 開頭,那麼剩下的 RE 都被當作 ARE。如果任何類型的 RE 以 ***=開頭, 那麼剩下的 RE 被當作一個文本串,所有的字符都被認為是一個普通字符。

一個 ARE 可以以嵌入選項開頭:一個(?xyz) 序列(這裡的 xyz 是一個或多個字母字符)聲明影響剩餘 RE 的選項。 這些選項覆蓋任何前面判斷的選項(包括 RE 風味和大小寫敏感性)。可用的選項字母 在 Table 9-19 顯示。

Table 9-19. ARE 嵌入選項字母

選項描述
b 剩下的 RE 是 BRE
c 大小寫敏感匹配(覆蓋操作符類型)
e 剩下的 RE 是 ERE
i 大小寫不敏感匹配(參閱 Section 9.6.3.5) (覆蓋操作符類型)
m n 的歷史同義詞
n 新行敏感匹配(參閱 Section 9.6.3.5
p 部分新行敏感匹配(參閱 Section 9.6.3.5
q 重置 RE 為一個文本("引起")字串,所有都是普通字符
s 非新行敏感匹配(缺省)
t 緊語法(缺省,見下文)
w 反轉部分新行敏感("怪異")匹配(參閱 Section 9.6.3.5
x 擴展的語法(見下文)

嵌入地選項在終止其序列的 ) 發生作用。他們只在 ARE 的開始處 起作用,稍後在裡面就不能再用了。

除了通常的()RE 語法,(這種情況下所有字符都重要), 還有一種擴展語法,可以通過聲明嵌入的 x 選項獲得。 在擴展語法裡,RE 中的空白字符被忽略,就像那些在 # 和新行之間 的字符一樣。這樣就允許我們給一個復雜的 RE 分段和注釋。不過這個基本規則 上有三種例外:

  • 前置了 \ 的空白字符或者 # 保留

  • 方括弧裡的空白或者 # 保留

  • 在多字符符號裡面,空白和注釋是非法的,就像 ARE (?: 或者 BRE \( 那樣。

擴展語法的空白是空白,水平制表符,新行,和任何屬于 space (空白)字符表的字符。

最後,在 ARE 裡,方括弧表達式外面,序列 (?#ttt) (這裡的 ttt 是任意不包含 ) 的文本)是一個注釋, 完全被忽略。同樣,這樣的東西是不允許出現在多字符符號的字符中間的, 比如 (?:。這樣的注釋是比有用的機制的更久遠的歷史造成的, 他們的用法已經廢棄了;我們應該使用擴展語法代替他。

如果聲明了一個初始化的 ***= 指示器,那麼所有這些元語法 擴展都不能使用,因為這樣表示把用戶輸入當作一個文本字串 而不是 RE 對待。

9.6.3.5. 正則表達式匹配規則

在 RE 可以匹配給出的字串中多于一個子字串的情況下, RE 匹配字串中最靠前的那個子字串。如果 RE 可以匹配在那個位置開始 的多個子字串,那麼它的選擇取決于它的喜好: 要麼是最長的子字串,要麼是最短的。

大多數原子,以及所有約束,都沒有喜好。一個圓括弧包圍的 RE 和這個 RE 有同樣的喜好(可能是沒有)。一個用量詞 {m} 或者 {m}?量化的原子和原子本身有著同樣的喜好(可能沒有)。 一個用其它普通量詞(包括 {m,n} 裡面 m 等于 n)量化的原子喜好最長的匹配。 一個用其它非貪婪的量詞(包括 {m,n}? 裡面的 m 等于 n)量化的原子喜好最短的匹配。 一個分支的喜好和它裡面的第一個有喜好的量化原子相同。 一個由 | 操作符連接起來得兩個或者多個分支喜好最長的匹配。

由規則強加匹配整個 RE 的約束,子表達式也匹配最長或者最短的字串, 以他們的喜好為基礎,在 RE 裡開始得早得子表達式得優先級高于開始的晚得。 請注意因此外層的子表達式的優先級高于它們的組件的子表達式。

量詞 {1,1}{1,1}? 可以分別用于 在一個子表達式或者整個 RE 上強制最長和最短喜好,

匹配長度是以字符衡量的,而不是集合的元素。一個空字串會被認為比什麼都不匹配長。 比如:bb* 匹配 abbbc 的中間三個字符; (week|wee)(night|knights) 匹配 weeknights 的所有十個字符; 而 (.*).* 匹配 abc的時候,圓括弧包圍的子表達式 匹配所有三個字符;而如果用 (a*)* 匹配 bc,那麼 RE 和圓括弧 子表達式都匹配整個字串。

如果聲明了大小寫無關的匹配,那麼效果就好像把所有字母上的 大小寫區別取消了一樣。如果一個存在大小寫差別的字母以一個 普通字符的形式出現在方括弧表達式外面,那麼它實際上被轉換成 一個包含大小寫的方括弧表達式,也就是說,x 變成 [xX]。 如果它出現在一個方括弧表達式裡面,那麼它的所有大小寫的同族都被加入 方括弧表達式中,也就是說,[x] 變成 [xX], 而 [^x] 變成 [^xX]

如果聲明了新行敏感匹配,. 和使用^的方括弧表達式 將永遠不會匹配新行字符(這樣,匹配就絕對不會誇新行,除非 RE 明確地安排了 這樣的情況)並且^$ 除了分別匹配 字串開頭和結尾之外,還將分別匹配新行後面和前面 的空字串。但是 ARE 逃逸 \A\Z 仍然匹配字串的開頭和結尾。

如果聲明了部分新行敏感匹配,那麼它影響 . 和方括弧表達式, 這個時候和新行敏感匹配一樣,但是不影響 ^$

如果聲明了反轉新行敏感匹配,那麼它影響 ^$, 作用和新行敏感匹配裡一樣,但是不影響 . 和方括弧表達式。 這個沒什麼太多用途,只是為了對稱提供的。

9.6.3.6. 限制和兼容性

在這個實現裡,對 RE 的長度沒有特別的限制,但是,那些希望能夠 有很好移植行的程序應該避免寫超過 256 字節的 RE,因為 POSIX 兼容 的實現可以拒絕接受這樣的 RE。

ARE 實際上和 POSIX ERE 不兼容的唯一的特性是在方括弧表達式裡 \ 並不 失去它特殊的含義。所有其它 ARE 特性都使用在 POSIX ERE 裡面是非法或者是 未定義、未聲明效果的語法;指示器的 *** 就是再 POSIX 的 BRE 和 ERE 之外的語法。

許多 ARE 擴展都是從 Perl 那裡借來的,但是有些我做了修改,清理了 一下,以及一些Perl裡沒有出現的擴展。要注意的不兼容包括 \b\B,對結尾的新行缺乏特別的處理,對那些新行敏感匹配的附加的 補齊方括弧表達式,在前瞻約束裡對圓括弧和方括弧引用的限制,以及最長/最短 匹配(而不是第一匹配)語義。

PostgreSQL 7.4 之前的版本裡的 ARE 和 ERE 存在兩個非常 顯著的不兼容:

  • 在 ARE 裡,後面跟著一個字母數字的 \ 要麼是一個逃逸,要麼是錯誤, 但是在以前的版本裡,她只是寫那個字母數字的另外一種方法。這個應該不是什麼問題, 因為在以前的版本裡沒有什麼原因讓我們寫這樣的序列。

  • 在 ARE 裡,\[]裡還是一個特殊字符, 因此在方括弧表達式裡的一個文本 \ 必須寫成 \\

雖然這些區別對大多數應用都來說都可能不是問題, 但必要時你可以通過設置 regex_flavorextended 來避免這些問題。

9.6.3.7. 基本正則表達式

BRE 在幾個方面和 ERE 不太一樣。|+,和 ? 都是普通字符,它們沒有等效的功能替換。範圍的分隔符是 \{\}, 因為 {} 本身是普通字符。嵌套的子表達式的圓括弧是 \(\),因為 () 自身是普通字符。 除非在 RE 開頭或者是圓括弧封裝的子表達式開頭,^ 都是普通字符, 除非在 RE 結尾或者是圓括弧封裝的子表達式的結尾,$ 是一個普通字符, 而如果 * 出現在 RE 開頭或者是圓括弧封裝的子表達式開頭 (前面可能有 ^ ),那麼它是個普通字符。 最後,可以用單數字的後引用,以及 \<\> 分別是 [[:<:]][[:>:]]的同義詞;沒有其它的逃逸。