Postgresql 正則表達式


在postgresql中使用正則表達式時需要使用關鍵字“~”,以表示該關鍵字之前的內容需匹配之后的正則表達式,若匹配規則不需要區分大小寫,可以使用組合關鍵字“~*”;

相反,若需要查詢不匹配這則表達式的記錄,只需在該關鍵字前加否定關鍵字“!”即可。若正則表達式包含轉義字符,則需在表達式前加關鍵字“E”。

例如:

select * from user where email ~ '^[A-H]' --匹配email地址以A-H開頭的記錄  
select * from user where email ~* '^[a-h]' --匹配email地址以A-H和a-h開頭的記錄 

9.7. 模式匹配

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

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

9.7.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.7.2. SIMILAR TO 正則表達式

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

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

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

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

  • | 標識選擇(兩個候選之一)。

  • * 表示重復前面的項零次或更多次。

  • + 表示重復前面的項一次或更多次。

  • 可以使用圓括弧 () 把項組合成一個邏輯項。

  • 一個方括弧表達式 [...] 聲明一個字符表, 就像 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), 提供了一個從字串中抽取一個匹配 SQL 正則表達式模式的子字串的函數。 和SIMILAR TO一樣,聲明的模式必須匹配整個數據串,否則函數失效並 返回 NULL。為了標識在成功的時候應該返回的模式部分,模式 必須出現后跟雙引號(")的兩個逃逸字符。匹配這兩個標記 之間的模式的字串將被返回。

一些例子:

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

 

9.7.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

 

regexp_replace 函數提供了將匹配 POSIX 正則表達式模式地子字串替換為信的文本的功能。 它的語法是 regexp_replace(source, pattern, replacement [, flags ])。 如果沒有匹配 pattern 的子字串,那么返回不加修改的 source 字串。 如果有匹配,則返回的 source 字串里面的對應子字串將被 replacement 字串替換掉。replacement 字串可以包含 \n, 這里的 n19, 表明源字串里匹配模式里第 n 個圓括弧子表達式的部分將插入在該位置, 並且它可以包含 \& 表示應該插入匹配整個模式的字串。 如果你需要放一個文本反斜杠在替換文本里,那么寫 \\。 (和通常一樣,記得在文本常量字串里寫雙反斜杠。)

Some examples:

regexp_replace('foobarbaz', 'b..', 'X')
                                   fooXbaz
regexp_replace('foobarbaz', 'b..', 'X', 'g')
                                   fooXX
regexp_replace('foobarbaz', 'b(..)', 'X\\1Y', 'g')
                                   fooXarYXazY

 

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

9.7.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來選擇 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.7.3.2 獲取更多細節)
\k (這里的 k 是非字母數字字符) 匹配一個當作普通字符看待的特定字符, 比如,\\ 匹配一個反斜杠
\c 這里的 c 是一個字母數字 (可能跟着其它字符),它是一個逃逸, 參閱 Section 9.7.3.3(僅存在於 ARE; 在 ERE 和 BRE 中,它匹配 c
{ 如果后面跟着一個字符,而不是數字, 那么就匹配左花括弧{;如果跟着一個數字, 那么它是范圍的開始(見下面)
x 這里的 x 是一個沒有其它特征的單個字符, 則匹配該字符

RE 不能以 \ 結尾。

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

'123' ~ '^\\d{3}' true

 

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.7.3.5 獲取細節。

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

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

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

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

9.7.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.7.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 和恰好四位十六進制位) 本機字節序的 UTF16 (Unicode,16 位) 字符 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.7.3.5 獲取它和 ^ 區別的信息)
\m 只匹配一個詞的開頭
\M 只匹配一個詞的結尾
\y 只匹配一個詞的開頭或者結尾
\Y 只匹配那些既不是詞的開頭也不是詞的結尾的點
\Z 只匹配一個字串的結尾 (參閱 Section 9.7.3.5 獲取它和$區別的信息)

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

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

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

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

9.7.3.4. 正則表達式元語法

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

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

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

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

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

嵌入地選項在終止其序列的 ) 發生作用。他們只在 ARE 的開始處起作用 (如果有,則在任何 ***: 指示器后面)。

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

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

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

  • 在多字符符號里面不能出現空白和注釋,比如 (?:

在這里,空白是空格,水平制表符,新行,和任何屬於 space (空白)字符表的字符。

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

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

9.7.3.5. 正則表達式匹配規則

在 RE 可以匹配給出的字串中多於一個子字串的情況下, RE 匹配字串中最靠前的那個子字串。如果 RE 可以匹配在那個位置開始 的多個子字串,要么是取最長的子字串,要么是最短的,具體哪種, 取決於 RE 是貪婪的 還是 非貪婪的

一個 RE 是否貪婪取決於下面規則:

  • 大多數原子,以及所有約束,都沒有貪婪屬性(因為它們畢竟無法匹配個數變化的文本)。

  • 在一個 RE 周圍加上圓括弧並不會改變其貪婪性。

  • 一個帶一個固定重復次數的量詞 ({m} 或者 {m}?) 之量化的原子和原子自身有着同樣的貪婪性(可能是沒有)。

  • 一個帶其他普通的量詞(包括 {m,n}m 等於 n 的情況)量化的原子是貪婪的(首選最長匹配)。

  • 一個帶非貪婪量詞(包括 {m,n}?m 等於 n 的情況)之量化原子是非貪婪的(首選最短匹配)。

  • 一個分支 — 也就是說,一個沒有頂級 | 操作的 RE — 和它里面的第一個有貪婪屬性的量化原子有着同樣的貪婪性。

  • 一個由 | 操作符連接起來的兩個或者更多分支組成的 RE 總是貪婪的。

 

上面的規則所描述的貪婪屬性不僅僅適用於獨立的量化原子, 而且也適用於包含量化原子的分支和整個 RE。這里的意思是, 匹配是按照分支或者整個 RE 作為一個整體匹配最長或者最短的子字串的可能。 一旦整個匹配的長度確定,那么匹配任意子表達式的部分就基於該子表達式的貪婪屬性進行判斷, 在 RE 里面靠前的子表達式的優先級高於靠后的子表達式。

一個表達這些的例子:

SELECT SUBSTRING('XY1234Z', 'Y*([0-9]{1,3})');
Result: 123
SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})');
Result: 1

在第一個例子里,RE 作為整體是貪婪的,因為 Y* 是貪婪的。 它可以匹配從 Y 開始的東西,並且它匹配從這個位置開始的最長的字串, 也就是,Y123。輸出是這里的圓括弧包圍的部分,或者說是 123。 在第二個例子里, RE 總體上是一個非貪婪的 RE,因為 Y*? 是非貪婪的。 它可以匹配從 Y 開始的最短的子字串,也就是說 Y1。 子表達式 [0-9]{1,3} 是貪婪的,但是它不能修改總體匹配長度的決定; 因此它被迫只匹配 1

簡單說,如果一個 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.7.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.7.3.7. 基本正則表達式

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

 

http://blog.csdn.net/wugewuge/article/details/7704996

http://www.php100.com/manual/PostgreSQL8/functions-matching.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM