?
このドキュメントでは、 php中國語ネットマニュアル リリース
PostgreSQL提供了三種實現(xiàn)模式匹配的方法:傳統(tǒng)SQL的LIKE
操作符、SQL99
新增的SIMILAR TO
操作符、POSIX風(fēng)格的正則表達(dá)式。另外還有一個模式匹配函數(shù)substring可用,
它可以使用SIMILAR TO
風(fēng)格或者POSIX風(fēng)格的正則表達(dá)式。
除了基本" ?"操作符,函數(shù)可用于提取或替換匹配的子串和分隔匹配位置的字符串。
Tip: 如果你的模式匹配要求比這些還多,或者想寫一些模式驅(qū)動的替換和轉(zhuǎn)換,請考慮用Perl或Tcl寫一個用戶定義函數(shù)。
LIKE
stringLIKEpattern[ESCAPEescape-character] stringNOT LIKEpattern[ESCAPEescape-character]
如果該string與所提供的pattern模式匹配,
那么LIKE
表達(dá)式返回真。和我們想像的一樣,如果LIKE
返回真,
那么NOT LIKE
表達(dá)式將返回假,反之亦然。一個等效的表達(dá)式
是NOT(stringLIKEpattern)。
如果pattern不包含百分號或者下劃線,那么該模式只代表它本身;這時候LIKE
的行為就像等號操作符。
在pattern里的下劃線(_)匹配任何單個字符;而一個百分號(%)匹配零或多個任何字符。
一些例子:
'abc' LIKE 'abc' true 'abc' LIKE 'a%'true 'abc' LIKE '_b_' true 'abc' LIKE 'c' false
LIKE
模式匹配總是覆蓋整個字符串。要匹配在字符串內(nèi)部任何位置的序列,該模式必須以百分號開頭和結(jié)尾。
要匹配下劃線或者百分號本身,在pattern里相應(yīng)的字符必須前導(dǎo)逃逸字符。 缺省的逃逸字符是反斜杠,但是你可以用ESCAPE子句指定一個。要匹配逃逸字符本身,寫兩個逃逸字符。
請注意反斜杠在字符串文本里已經(jīng)有特殊含義了,所以如果你寫一個包含反斜杠的模式常量,
那你就要在 SQL 語句里寫兩個反斜杠。因此,寫一個匹配單個反斜杠的模式實際上要在語句里
寫四個反斜杠。你可以通過用ESCAPE選擇一個不同的逃逸字符來避免這樣;這樣反斜杠就
不再是LIKE
的特殊字符了。(但仍然是字符文本分析器的特殊字符,所以你還是需要兩個反斜杠。)
我們也可以通過寫成ESCAPE ''的方式關(guān)閉逃逸機(jī)制,這時,我們就不能關(guān)閉下劃線和百分號的特殊含義
關(guān)鍵字ILIKE可以用于替換LIKE, 令該匹配就當(dāng)前的區(qū)域設(shè)置是大小寫無關(guān)的。這個特性不是SQL標(biāo)準(zhǔn), 是PostgreSQL擴(kuò)展。
操作符~~等效于LIKE
,而~~*等效于ILIKE
。
還有!~~和!~~*操作符分別
代表NOT LIKE
和NOT ILIKE
。所有這些操作符都是PostgreSQL特有的。
SIMILAR TO
正則表達(dá)式stringSIMILAR TOpattern[ESCAPEescape-character] stringNOT SIMILAR TOpattern[ESCAPEescape-character]
SIMILAR TO
根據(jù)自己的模式是否匹配給定字符串而返回真或假。
它和LIKE
非常類似,只不過它使用 SQL 標(biāo)準(zhǔn)定義的正則表達(dá)式理解模式。
SQL 標(biāo)準(zhǔn)的正則表達(dá)式是在LIKE
表示法和普通的正則表達(dá)式表示法之間古怪的交叉。
類似LIKE
, theSIMILAR TO
操作符只有在它的模式匹配整個字符串的時候才能成功;
這一點和普通的正則表達(dá)式的習(xí)慣不同,在普通的正則表達(dá)式里,模式匹配字符串的任意部分。
和LIKE
類似的地方還有SIMILAR TO
使用
_ 和 % 分別匹配單個字符和任意字符串(這些和 POSIX 正則表達(dá)式里的_和%兼容)。
除了這些從 LIKE 借用的功能之外,SIMILAR TO
支持下面這些從 POSIX 正則表達(dá)式借用的模式匹配元字符:
|表示選擇(兩個候選之一).
*表示重復(fù)前面的項零次或更多次
+表示重復(fù)前面的項一次或更多次
? 表示重復(fù)前面的項零或一次。
{m} 表示重復(fù)前面的項,完全相同m次。
{m,} 表示重復(fù)前面的項m或更多次。
{m,n} 表示重復(fù)前面的項至少m次,不超過n次。
括號()可以作為項目分組到一個獨立的邏輯項。
[...]聲明一個字符類,就像POSIX正則表達(dá)式。
請注意之間的 (.)不是一個元字符而是SIMILAR TO
。
和LIKE
一樣,反斜杠關(guān)閉所有這些元字符的特殊含義;
當(dāng)然我們也可以用ESCAPE聲明另外一個逃逸字符。
一些例子:
'abc' SIMILAR TO 'abc' true 'abc' SIMILAR TO 'a' false 'abc' SIMILAR TO '%(b|d)%'true 'abc' SIMILAR TO '(b|c)%'false
三個參數(shù)的substring(string from pattern for escape-character)
函數(shù)提供了
一個從字符串中抽取一個匹配 SQL 正則表達(dá)式模式的子字符串功能。和SIMILAR TO一樣,
聲明的模式必須匹配整個字符串,否則函數(shù)失效并返回 NULL 。為了標(biāo)識在成功的時候應(yīng)該返回的模式部分,
模式必須出現(xiàn)后跟雙引號(")的兩個逃逸字符。匹配這兩個標(biāo)記之間的模式的字符串將被返回。
一些例子,用#"分隔返回字符串:
substring('foobar' from '%#"o_b#"%' for '#')oob substring('foobar' from '#"o_b#"%' for '#') NULL
Table 9-11列出了所可用的POSIX 正則表達(dá)式的模式匹配操作符
Table 9-11. 正則表達(dá)式匹配操作符
操作符 | 描述 | 示例 |
---|---|---|
~ | 匹配正則表達(dá)式,區(qū)分大小寫 | 'thomas' ~ '.*thomas.*' |
~* | 匹配正則表達(dá)式,不分大小寫 | 'thomas' ~* '.*Thomas.*' |
!~ | 不匹配正則表達(dá)式,區(qū)分大小寫 | 'thomas' !~ '.*Thomas.*' |
!~* | 不匹配正則表達(dá)式,不分大小寫 | 'thomas' !~* '.*vadim.*' |
POSIX正則表達(dá)式提供了比LIKE
和SIMILAR TO
操作符更強(qiáng)大的模式匹配的方法。許多 Unix 工具,比如egrep,
sed,awk使用類似的模式匹配語言。
正則表達(dá)式是一個字符序列,它是定義一個字符串集合(一個正則集合)的縮寫。
如果一個字符串是正則表達(dá)式描述的正則集合中的一員時,我們就說這個字符串匹配該正則表達(dá)式。
和LIKE
一樣,模式字符準(zhǔn)確地匹配字符串字符,除非在正則表達(dá)式語言里有特殊
字符(不過正則表達(dá)式用的特殊字符和LIKE
用的不同)。和LIKE
不一樣的是,
正則表達(dá)式可以匹配字符串里的任何位置,除非該正則表達(dá)式明確地錨定在字符串的開頭或者結(jié)尾。
一些例子:
'abc' ~ 'abc' true 'abc' ~ '^a'true 'abc' ~ '(b|d)'true 'abc' ~ '^(b|c)'false
下面更詳細(xì)描述POSIX模式匹配語言。
兩個參數(shù)的substring(stringfrom
pattern)
函數(shù)提供了從字符串中抽取一個
匹配 POSIX 正則表達(dá)式模式的子字符串的方法。如果沒有匹配它返回 NULL ,
否則就是文本中匹配模式的那部分。但是如果該模式包含任何圓括弧,那么將返回匹配
第一對子表達(dá)式(對應(yīng)第一個左圓括弧的)的文本。如果你想在表達(dá)式里使用圓括弧而又不想
導(dǎo)致這個例外,那么你可以在整個表達(dá)式外邊放上一對圓括弧。
如果你需要在想抽取的子表達(dá)式前有圓括弧,參閱描述的非捕獲性圓括弧。
一些例子:
substring('foobar' from 'o.b')oob substring('foobar' from 'o(.)b')o
regexp_replace
(source,
pattern,replacement
[,flags]) 函數(shù)提供了將匹配
POSIX 正則表達(dá)式模式的子字符串替換為新文本的功能。如果沒有匹配pattern的子字符串,
那么返回不加修改的source字符串。如果有匹配,則返回的source字符串里面的對應(yīng)子字符串
將被 replacement 字符串替換掉。replacement字符串可以包含\n,
這里的n是1到9,
表明源字符串中匹配第n個圓括弧子表達(dá)式的部分將插入在該位置,并且它可以包含\&表示
應(yīng)該插入匹配整個模式的字符串。如果你需要放一個文本反斜杠在替換文本里,那么寫\\(和
通常一樣,記得在文本常量字符串里寫雙反斜杠)??蛇x的flags參數(shù)包含零個或多個改變函數(shù)行為的單字母標(biāo)記。
i表示進(jìn)行大小寫無關(guān)的匹配,g表示替換每一個匹配的子字符串而不僅僅是第一個。
其它支持的標(biāo)記描述在Table 9-19。
一些例子:
regexp_replace('foobarbaz', 'b..', 'X') fooXbaz regexp_replace('foobarbaz', 'b..', 'X', 'g') fooXX regexp_replace('foobarbaz', 'b(..)', E'X\\1Y', 'g') fooXarYXazY
regexp_matches
函數(shù)返回一個所有匹配POSIX正則表達(dá)式的獲取子串結(jié)果的text數(shù)組。使用語法
regexp_matches
(string,pattern
[,flags])。這個函數(shù)可以返回沒有行,一行,或者多行
(參閱下面的g標(biāo)記)。如果pattern沒有匹配,則函數(shù)返回沒有行。
如果模式包含沒有括號的子表達(dá)式,則每行返回的是單元素的文本數(shù)組,其中包含的子串相匹配整個模式。
如果模式包含括號的子表達(dá)式,函數(shù)返回一個文本數(shù)組,n的元素是子串匹配n括號子表達(dá)式內(nèi)的模式。
(不計"非捕獲"的括號);詳細(xì)信息參閱下面的。
參數(shù)flags是一個選項text字符串,含有0或者更多單字母標(biāo)記來改變函數(shù)行為。標(biāo)記g導(dǎo)致查找字符串中的每個匹配,
而不僅是第一個,每個匹配返回一行,其它的標(biāo)記支持描述在Table 9-19。
一些例子:
SELECT regexp_matches('foobarbequebaz', '(bar)(beque)'); regexp_matches ---------------- {bar,beque} (1 row) SELECT regexp_matches('foobarbequebazilbarfbonk', '(b[^b]+)(b[^b]+)', 'g'); regexp_matches ---------------- {bar,beque} {bazil,barf} (2 rows) SELECT regexp_matches('foobarbequebaz', 'barbeque'); regexp_matches ---------------- {barbeque} (1 row)
使用select子句,可能強(qiáng)制regexp_matches()
總是返回一行;
在SELECT當(dāng)你想要的所有行的目標(biāo)列表返回,甚至不匹配的情況下,是有特別有用的。
SELECT col1, (SELECT regexp_matches(col2, '(bar)(beque)')) FROM tab;
regexp_split_to_table
函數(shù)使用POSIX正則表達(dá)式作為分隔符,分隔字符串。
語法regexp_split_to_table
(string,pattern
[,flags])。如果沒有匹配pattern,函數(shù)將返回string。
如果有至少一個匹配,每個匹配返回從最后一個匹配結(jié)束(或者字符串的開頭)到匹配開始的文本。
當(dāng)沒有更多的匹配,返回最后一個匹配的結(jié)束到字符串的結(jié)束的文本。
flags參數(shù)是一個選項text字符串,含有0或者更多單字母標(biāo)記來改變函數(shù)行為。
regexp_split_to_table
支持的標(biāo)記描述在Table 9-19。
除了regexp_split_to_array
返回結(jié)果為text數(shù)組,regexp_split_to_array
函數(shù)行為與regexp_split_to_table
相同, 使用語法
regexp_split_to_array
(string,pattern
[,flags])。
參數(shù)與regexp_split_to_table
相同。
一些例子:
SELECT foo FROM regexp_split_to_table('the quick brown fox jumped over the lazy dog', E'\\s+') AS foo; foo -------- the quick brown fox jumped over the lazy dog (9 rows) SELECT regexp_split_to_array('the quick brown fox jumped over the lazy dog', E'\\s+'); regexp_split_to_array ------------------------------------------------ {the,quick,brown,fox,jumped,over,the,lazy,dog} (1 row) SELECT foo FROM regexp_split_to_table('the quick brown fox', E'\\s*') AS foo; foo ----- t h e q u i c k b r o w n f o x (16 rows)
作為最后一個例子表明,在出現(xiàn)在字符串的開始或結(jié)束
或在緊接一前一后的匹配,正則表達(dá)式分隔函數(shù)忽略零長度匹配,
這樣實現(xiàn)regexp_matches
嚴(yán)格上來說是違背了的
正則表達(dá)式匹配的定義,但在實際使用中,通常是最便利的的行為。
如Perl等軟件系統(tǒng),使用了類似的定義。
PostgreSQL的正則表達(dá)式使用 Henry Spencer 寫的一個包來實現(xiàn)。 下面的大部分描述都是從他的手冊頁里逐字拷貝過來的。
正則表達(dá)式(REs),在POSIX1003.2中定義, 它有兩種形式:擴(kuò)展正則表達(dá)式extendedREs或 EREs(基本上就是在egrep里的那些), 基本正則表達(dá)式basicREs或 BREBREs(基本上就是在 eded里的那些)。 PostgreSQL支持這兩種形式,也實現(xiàn)了一些POSIX 里面沒有的,在 Perl 或Tcl 這樣的語言中得到廣泛應(yīng)用的類似擴(kuò)展。使用了那些非 POSIX 擴(kuò)展的正則表達(dá)式叫 高級正則表達(dá)式advancedREs或AREs。 AREs幾乎完全是EREs的超集,但是BREs有幾個符號上的不兼容(以及更多的限制)。 我們首先描述AREs和EREs形式, 描述那些只適用于AREs的特性,然后描述與BREs的區(qū)別是什么。
Note: PostgreSQL總是初始化一個遵循ARE規(guī)則的正則表達(dá)式。然而對于RE模式,可以在 更多限制的ERE或BRE規(guī)則前面,選擇一個embedded option,描述在Section 9.7.3.4。 這對于兼容期望完全POSIX1003.2規(guī)則的應(yīng)用程序,是有用的。
一條正則表達(dá)式可以定義為一個或多個的分支,由|分隔。 它要匹配其中任何一個分支。
一個分支是0或多個限定的原子quantified atoms或約束constraints連接而成。 一個原子匹配第一個,后面的原子匹配第二個,依次類推。一個空的分支要匹配空字符串。
一個有限定的原子是一個原子atom,后面可能跟著一個界定符quantifier。沒有界定符的時候, 它匹配一個原子,有界定符的時候,它可以匹配若干個原子。 原子的各種可能性,在atom在Table 9-12里面顯示??赡艿慕缍ǚ退麄兊暮x在Table 9-13里顯示。
一個約束constraint匹配一個空字符串, 但只是在滿足特定條件下才匹配。約束可以在能夠使用原子的地方使用, 只是它不能跟著界定符。簡單的約束在Table 9-14里顯示;稍后描述更多的約束。
Table 9-12. 正則表達(dá)式原子
原子 | 描述 |
---|---|
(re) | (re是任意正則表達(dá)式)匹配一個對 re 的匹配,有可報告的匹配信息。 |
(?:re) | as above, but the match is not noted for reporting (a"non-capturing"set of parentheses) (AREs only) 同上,但是不會報告匹配信息(一個"非捕獲"non-capturing""括號),只在 ARE 中有。 |
. | 匹配任意單個字符 |
[chars] | 一個方括弧表達(dá)式bracket expression,匹配chars中的任意字符 (參閱Section 9.7.3.2獲取更多細(xì)節(jié))。 |
\k | (k是非字母數(shù)字字符)匹配一個當(dāng)作普通字符看待的特定字符,比如\\匹配一個反斜杠。 |
\c | c是一個字母數(shù)字(可能跟著其它字符),首項是逃逸符escape,參閱Section 9.7.3.3。 (僅在ARE 中;在 ERE 和 BRE 中,它匹配c)。 |
{ | when followed by a character other than a digit, matches the left-brace character{; when followed by a digit, it is the beginning of a bound(see below) 如果后面跟著一個非數(shù)字字符,那么就 匹配左花括弧{;如果跟著一個數(shù)字,那么它是范圍bound的開始(見下面) |
x | 這里的x是一個沒有其它特征的單個字符,則匹配該字符。 |
RE不能以\結(jié)尾。
Note: 要記住反斜杠(\)在PostgreSQL字符串文本中已經(jīng)有特殊含義了。 要寫一個包含反斜杠的模式,你必須在語句里寫兩個反斜杠(參閱Section 4.1.2.1)。
Table 9-13. 正則表達(dá)式界定符
界定符 | 匹配 |
---|---|
* | 一個匹配0或更多個原子的序列 |
+ | 一個匹配 1或更多個原子的序列 |
? | 一個匹配0或1個原子的序列 |
{m} | 一個正好匹配m個原子的序列 |
{m,} | 一個匹配m個或者更多原子的序列 |
{m,n} | 一個匹配m到n個(包含兩端)原子的序列;m不能比n大 |
*? | *的非貪婪模式 |
+? | +的非貪婪模式 |
?? | ?的非貪婪模式 |
{m}? | {m}的非貪婪模式 |
{m,}? | {m,}的非貪婪模式 |
{m,n}? | {m,n}的非貪婪模式 |
{...}的形式被稱作范圍bounds。 一個范圍內(nèi)的數(shù)字m和n都是無符號十進(jìn)制整數(shù),允許的數(shù)值從 0 到 255 (閉區(qū)間)。
Non-greedy界定符(只在 ARE 中可用)匹配對應(yīng)的正常(greedy)模式, 區(qū)別是它尋找最少的匹配,而不是最多的匹配。參閱Section 9.7.3.5獲取更多細(xì)節(jié)。
Note: 一個界定符不能緊跟在另外一個界定符后面。例如,**是無效的。界定符不能是表達(dá)式或者子表達(dá)式的開頭, 也不能跟在^或|后面。
Table 9-14. 正則表達(dá)式約束
約束 | 描述 |
---|---|
^ | 匹配字符串的開頭 |
$ | 匹配字符串的結(jié)尾 |
正向預(yù)查positive lookahead在任何匹配re的字符串開始處匹配查找字符串(只在 ARE 中有)。 | ? |
(?!re) | 負(fù)向預(yù)查negative lookahead在任何不匹配re的字符串開始處匹配查找字符串(只在 ARE 中有)。 |
預(yù)查約束不能包含后引用back references(參閱Section 9.7.3.3),并且在其中的所有圓括號都被認(rèn)為是不捕獲的。
方括號表達(dá)式bracket expression是一個[]括起來的字符列表。它通常匹配任意單個列表中的 字符(又見下文)。如果列表以^開頭,它匹配任意單個不在該列表中的字符。 如果該列表中兩個字符用-隔開,那它就是那兩個字符(包括在內(nèi))之間的所有字符范圍的縮寫, 比如,在ASCII里[0-9]匹配查找任何十進(jìn)制數(shù)字。兩個范圍共享一個終點是非法的, 比如a-c-e。這個范圍與序列順序關(guān)系密切,可移植的程序不應(yīng)該依靠它們。
在列表中包含文本],可以讓它做列表的首字符(可能會在一個^后面)。 在列表中包含文本-,可以讓它做列表的首字符或者末字符,或者一個范圍的第二個終點。 在列表中把文本-當(dāng)做范圍的起點,把它用[.and.]包圍起來,這樣它就成為一個 集合元素(見下文)。除了這些字符本身,和一些用[的組合(見下段), 以及逃逸(只在 ARE 中有效)以外,所有其它特殊字符在方括弧表達(dá)式里都失去它們的特殊含義。 特別是,在 ERE 和 BRE 規(guī)則下\不是特殊的,但在 ARE 里,它是特殊的(還是引入一個逃逸)。
在一個方括弧表達(dá)式里,一個集合元素(一個字符、一個當(dāng)做一個字符的多字符序列、或者 一個表示上面兩種情況的集合序列)包含在[.和.]里面的時候表示該集合元素的字符序列。 該序列是該方括弧列表的一個元素。因此一個包含多字符集合元素的方括弧表達(dá)式就可以 匹配多于一個字符,比如,如果集合序列包含一個ch集合元素,那么[[.ch.]]*c 匹配chchcc的頭五個字符。 譯注:其實把 [. 和 .] 括起來的整體當(dāng)一個字符看就行了。
Note: PostgreSQL目前不支持多字節(jié)符集合元素。這些信息描述了將來可能有的行為。
在方括弧表達(dá)式里,在[=和=]括起來的集合元素是一個等價表, 代表等于這里所有集合元素的字符序列,包括它本身(如果沒有其它等效集合元素, 那么就處理如同由[.和.].)的界定符。例如, 如果o和^是一個等價類的成員, 那么[[=o=]],[[=^=]],[o^]都是同義的。一個等價表不能是一個范圍的端點。
在方括弧表達(dá)式里,在[:和:]里面括起來的字符表名,代表屬于該表的所有字符的列表。 標(biāo)準(zhǔn)的字符表名字是:alnum, alpha,blank, cntrl,digit, graph,lower, print,punct, space,upper, xdigit。它們代表 在ctype里定義的字符表。 本地化設(shè)置可能會提供其它的表。字符表不能用做一個范圍的端點。
在方括弧表達(dá)式里有兩個特例:方括弧表達(dá)式[[:<:]]和[[:>:]]是約束, 分別匹配一個單詞開頭和結(jié)束的空串。單詞定義為一個單詞字符序列,前面和后面 都沒有其它單詞字符。單詞字符是一個alnum字符(和ctype) 里定義的一樣)或者一個下劃線。這是一個擴(kuò)展,兼容POSIX1003.2 ,但那里面并沒有說明,而且在準(zhǔn)備移植到其它系統(tǒng)里去的軟件里一定要小心使用。 通常下面描述的約束逃逸更好些(他們并非更標(biāo)準(zhǔn),但是肯定更容易輸入)。
Escapes是以\開頭,后面跟著一個字母數(shù)字字符的特殊序列。逃逸有好幾種 變體:字符項、表縮寫、約束逃逸、后引用。在 ARE 里,如果一個\后面跟著一個 字母數(shù)字,但是并未組成一個合法的逃逸,那么它是非法的。在 ERE 里則沒有逃逸:在 方括弧表達(dá)式之外,一個跟著字母數(shù)字字符的\只是表示該字符是一個普通字符, 而在一個方括弧表達(dá)式里,\是一個普通的字符(后者實際上是 ERE 和 ARE 之間的不兼容)。
字符項逃逸Character-entry escapes用于方便我們聲明正則表達(dá)式里那些不可打印和在RE里其它不方便的字符。 它們在Table 9-15里列出。
類縮寫逃逸Class-shorthand escapes用來提供一些常用的字符類縮寫。他們在Table 9-16里列出
約束逃逸constraint escape是一個約束,如果滿足特定的條件,它匹配該空字符串,作為逃逸編寫。 它們在Table 9-17里列出。
后引用back reference(\n)匹配數(shù)字n 指定前面圓括弧子表達(dá)式匹配的同一個字符串(參閱Table 9-18)。 例如,(([bc])\1匹配bb或cc但是不匹配bc或cb。 正則表達(dá)式里的子表達(dá)式必須完全在后引用前面。非捕獲圓括弧并不定義子表達(dá)式。
Note: 請記住,如果把模式當(dāng)作一個 SQL 字符串常量輸入,那么逃逸前導(dǎo)的\需要雙倍地寫。例如:
'123' ~ E'^\\d{3}'true
Table 9-15. 正則表達(dá)式字符項逃逸
逃逸 | 描述 |
---|---|
\a | 警笛(鈴聲)字符,和 C 里一樣 |
\b | 退格,和 C 里一樣 |
\B | \的同義詞,用于減少反斜杠加倍的需要 |
\cX | (這里X是任意字符)字符的低5位和X里的相同,其它位都是0。 |
\e | 集合序列名字是ESC的字符,如果不是,則是八進(jìn)制值為033的字符 |
\f | 進(jìn)紙,和C里一樣 |
\n | 新行,和C里一樣 |
\r | 回車,和C里一樣 |
\t | 水平制表符,和C里一樣 |
\uwxyz | (這里的wxyz是恰好四個十六進(jìn)制數(shù)字)本機(jī)字節(jié)序的 UTF-16(寬字符,16位)字符U+wxyz。 |
\Ustuvwxyz | (wherestuvwxyzis exactly eight hexadecimal digits) reserved for a hypothetical Unicode extension to 32 bits (這里的stuvwxyz是恰好八個十六進(jìn)制數(shù)字)為Unicode 32 位擴(kuò)展預(yù)留的。 |
\v | 垂直制表符,和 C 里一樣 |
\xhhh | (這里的hhh是一個十六進(jìn)制序列)十六進(jìn)制 值為0xhhh的字符(不管用了幾個十六進(jìn)制位,都是一個字符)。 |
\0 | 值為0的字符(空字節(jié)) |
\xy | (這里的xy是恰好兩個八進(jìn)制數(shù)字,并且不是一個back reference后引用)八進(jìn)制值為0xy的字符 |
\xyz | (這里的xyz是恰好三位八進(jìn)制位,并且不是一個 后引用)八進(jìn)制值為0xyz的字符 |
十六進(jìn)制數(shù)字是0-9,a-f,A-F。八進(jìn)制數(shù)字是0-7。
字符項逃逸總是被當(dāng)作普通字符。例如,\135是 ASCII 中的], 但\135并不結(jié)束一個方括弧表達(dá)式。
Table 9-16. 正則表達(dá)式類縮寫逃逸
逃逸 | 描述 |
---|---|
\d | [[:digit:]] |
\s | [[:space:]] |
\w | [[:alnum:]_] (注意,這里是包含下劃線的) |
\D | [^[:digit:]] |
\S | [^[:space:]] |
\W | [^[:alnum:]_] (注意,這里是包含下劃線的) |
在方括號表達(dá)式里,\d,\s, \w會失去他們的外層方括號,而\D,\S,\W是非法的。 比如[a-c\d]等效于[a-c[:digit:]]。 同樣[a-c\D]原來等效于[a-c^[:digit:]]的,也是非法的。
Table 9-17. 正則表達(dá)式約束逃逸
逃逸 | 描述 |
---|---|
\A | 只匹配字符串開頭(參閱Section 9.7.3.5獲取它和^區(qū)別的信息) |
\m | 只匹配一個詞的開頭 |
\M | 只匹配一個詞的結(jié)尾 |
\y | 只匹配一個詞的開頭或者結(jié)尾 |
\Y | 只匹配那些既不是詞的開頭也不是詞的結(jié)尾的點 |
\Z | 只匹配一個字符串的結(jié)尾(參閱Section 9.7.3.5獲取它和$區(qū)別的信息) |
一個詞的定義是上面[[:<:]]和[[:>:]]的聲明。 在方括弧表達(dá)式里,約束逃逸是非法的。
Table 9-18. 正則表達(dá)式后引用
逃逸 | 描述 |
---|---|
\m | 這里的m是一個非零數(shù)字)一個指向第m個子表達(dá)式的后引用 |
\mnn | (這里的m是一個非零數(shù)字,nn是更多的數(shù)字,并且十進(jìn)制數(shù)值mnn 不能大于到這個位置為止的閉合捕獲圓括號的個數(shù))一個指向第 mnn 個子表達(dá)式的后引用。 |
Note: 在八進(jìn)制字符項逃逸和后引用之間有一個歷史繼承的歧義存在,這個歧義是 通過啟發(fā)分析解決的,像上面描述的那樣。前導(dǎo)零總是表示這是一個八進(jìn)制逃逸。 而單個非零數(shù)字,如果沒有跟著任何其它數(shù)字,那么總是認(rèn)為是后引用。 一個多數(shù)據(jù)位的非零開頭的序列也認(rèn)為是后引用(只要它在合適的子表達(dá)式后面, 也就是說,數(shù)值在后引用的合法范圍內(nèi)),否則就認(rèn)為是一個八進(jìn)制。
除了上面描述的主要語法之外,還有幾種特殊形式和雜項語法。
正則表達(dá)式可以用兩個特殊意義的director前綴其中之一。 如果一個正則表達(dá)式以***:開頭,正則表達(dá)式其余部分,可以作為ARE。 (在正則表達(dá)式作為ARE后,這通常在PostgreSQL沒有影響的;但是 如果在ERE或BRE模式指定一個flags參數(shù)給正則表達(dá)式函數(shù),確實是有影響的。) 如果一個正則表達(dá)式以***=開頭,正則表達(dá)式其余部分作為文本字符串, 所有字符串視為普通字符。
ARE可以用embedded options開頭;一個序列(?xyz) (這里xyz是1個或更多個字母字符)特定的選項影響正則表達(dá)式的其余部分。 這些選項覆蓋任何先前確定的選項 —尤其,他們可以覆蓋正則表達(dá)式操作符或flags 給正則表達(dá)式函數(shù)的隱含區(qū)分大小寫的行為??捎玫淖帜高x項顯示在Table 9-19。 注意同樣這些字母選項可以用作正則表達(dá)式函數(shù)的flags參數(shù)。
Table 9-19. ARE 嵌入選項字母
選項 | 描述 |
---|---|
b | 正則表達(dá)式的其余部分是BRE |
c | 大小寫敏感匹配(覆蓋操作符類型) |
e | 正則表達(dá)式的其余部分是 ERE |
i | 大小寫不敏感匹配(參閱Section 9.7.3.5)(覆蓋操作符類型) |
m | n的歷史同義詞 |
n | 換行敏感匹配(參閱Section 9.7.3.5) |
p | 部分換行敏感匹配(參閱Section 9.7.3.5) |
q | 正則表達(dá)式的其余部分為一個文本("quoted")字符串,所有都是普通字符 |
s | 非換行敏感匹配(缺省) |
t | 嚴(yán)格的語法(缺省,見下文) |
w | 反部分換行敏感("怪異""weird")匹配(參閱Section 9.7.3.5) |
x | 擴(kuò)展的語法(見下文) |
嵌入的選項在終止其序列的)發(fā)生作用。他們只在 ARE 的開始處起作用(即在任何***:引導(dǎo)符后面)。
除了通常情況下所有的選項字符都顯然遵循(嚴(yán)格tight)正則表達(dá)式語法,還有 一種擴(kuò)展expanded語法,可以通過聲明嵌入的x選項使用。在擴(kuò)展語法里, 正則表達(dá)式中的空白字符被忽略,就像那些在#和新行后(或正則表達(dá)式的結(jié)尾處)之間的所有字符一樣。這樣就允許 我們給一個復(fù)雜的正則表達(dá)式分段和注釋。不過這個基本規(guī)則上有三種例外:
前置了\的空白符或#保留
在方括號表達(dá)式里的空白符或者#保留
在多個字符符號里面不能出現(xiàn)空白和注釋,比如(?:。
在這里,空白是空白、水平制表符、換行、和任何屬于space(空白)字符表的字符。
最后,在 ARE 里,方括號表達(dá)式外面,序列(?#ttt)(這里的ttt是任意不包含) 的文本)是一個注釋,完全忽略掉。再次,在多字符符號里,不允許使用,例如(?:。這樣的注釋是比一個有用的工具更歷史些, 他們的用法已經(jīng)廢棄了;我們應(yīng)該使用擴(kuò)展語法代替他。
如果聲明了一個初始化的***=引導(dǎo)符,那么所有這些元語法擴(kuò)展都不能使用, 因為這樣表示把用戶輸入當(dāng)作一個文本字符串而不是正則表達(dá)式對待。
在正則表達(dá)式可以匹配給出的字符串中多于一個子串的情況下,正則表達(dá)式 匹配字符串中最早開始匹配的那個子串。如果正則表達(dá)式可以匹配多個子串在那些位置開始處,要么是匹配最長的, 要么是最短的,具體哪種,取決于正則表達(dá)式是貪婪greedy的還是非貪婪non-greedy的。
一個正則表達(dá)式是否貪婪取決于下面規(guī)則:
大多數(shù)原子,以及所有約束,都沒有貪婪屬性(因為它們畢竟無法匹配變量的文本)。
在一個正則表達(dá)式周圍加上圓括號并不會改變其貪婪性。
一個帶有固定重復(fù)次數(shù)的界定符(({m}或 {m}?)的量化原子和原子自身有著同樣的貪婪性(可能是沒有)。
一個帶其它普通的量詞(包括{m,n}中 m等于n的情況)量化的原子是貪婪的(首選最長匹配)。
一個帶非貪婪量詞(包括{m,n}? 中m等于n的情況)量化原子是非貪婪的(首選最短匹配)。
一個分支(也就是一個沒有頂級|操作符的 正則表達(dá)式)和它里面的第一個有貪婪屬性的量化原子有著同樣的貪婪性。
一個由|操作符連接起來的兩個或者更多分支組成的正則表達(dá)式總是貪婪的。
上面的規(guī)則所描述的貪婪屬性不僅僅適用于獨立的量化原子,而且也適用于 包含量化原子的分支和整個正則表達(dá)式。這里的意思是,匹配是按照分支或者整個 正則表達(dá)式作為一個整體匹配最長或者最短的子字符串的可能。一旦整個 匹配的長度確定,那么匹配任意子表達(dá)式的部分就基于該子表達(dá)式的貪婪屬性進(jìn)行判斷, 在正則表達(dá)式里面靠前的子表達(dá)式的優(yōu)先級高于靠后的子表達(dá)式。
一個表達(dá)這些意思的例子:
SELECT SUBSTRING('XY1234Z', 'Y*([0-9]{1,3})'); Result:123 SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})'); Result:1
在第一個例子里,正則表達(dá)式作為整體是貪婪的,因為Y*是貪婪的。 它可以匹配從Y開始的東西,并且它匹配從這個位置開始的最長的字符串, 也就是Y123。輸出是這里的圓括弧包圍的部分,或者說是123。在第二個例子里, 正則表達(dá)式總體上是一個非貪婪的正則表達(dá)式 ,因為Y*?是非貪婪的。它可以匹配 從Y開始的最短的子字符串,也就是說Y1。子表達(dá)式[0-9]{1,3}是貪婪的, 但是它不能修改總體匹配長度的決定;因此它被迫只匹配1。
簡單說,如果一個正則表達(dá)式同時包含貪婪和非貪婪的子表達(dá)式,那么總匹配長度要么是最長可能,要么是最短可能, 取決于給整個正則表達(dá)式賦予的貪婪屬性。給子表達(dá)式賦予的貪婪屬性只影響在這個匹配里, 各個子表達(dá)式之間相互允許"吃進(jìn)"eat""的多少。
量詞{1,1}和{1,1}?可以分別用于在一個子表達(dá)式或者整個正則表達(dá)式上強(qiáng)制貪婪或者非貪婪。
匹配長度是以字符衡量的,而不是集合的元素。一個空字符串會被認(rèn)為 比什么都不匹配長。比如:bb*匹配abbbc的中間三個字符; (week|wee)(night|knights)匹配weeknights的所有十個字符; 而(.*).*匹配abc的時候,圓括號包圍的子表達(dá)式匹配所有三個字符; 而如果用(a*)*匹配bc,那么整個正則表達(dá)式和圓括號子表達(dá)式都匹配一個空字符串。
如果聲明了大小寫無關(guān)的匹配,那么效果就好像把所有字母上的大小寫區(qū)別 取消了一樣。如果一個存在大小寫差別的字母以一個普通字符的形式出現(xiàn)在方括弧 表達(dá)式外面,那么它實際上被轉(zhuǎn)換成一個包含大小寫的方括弧表達(dá)式,也就是說, x變成[xX]。如果它出現(xiàn)在一個方括弧表達(dá)式里面,那么它的所有大小寫的同族都被加入 方括弧表達(dá)式中,也就是說,[x]變成[xX]而[^x]變成[^xX]。
如果聲明了換行敏感匹配,.和使用^的方括弧表達(dá)式將永遠(yuǎn)不會匹配換行字 符(這樣,匹配就絕對不會跨換行,除非正則表達(dá)式明確地指定了這樣的情況)并 且^和$除了分別匹配字符串開頭和結(jié)尾之外,還將分別匹配換行后面和前面的 空字符串。但是 ARE 逃逸\A和\Z仍然只配字符串的開頭和結(jié)尾。
如果聲明了部分換行敏感匹配,那么它影響.和 方括弧表達(dá)式,這個時候和換行敏感匹配一樣,但是不影響^和$.。
如果聲明了反轉(zhuǎn)換行敏感匹配,那么它影響^和$,作用和換行敏感匹配里一樣, 但是不影響.和方括號表達(dá)式。這個沒什么太多用途,只是為了對稱提供的。
在這個實現(xiàn)里,對正則表達(dá)式的長度沒有特別的限制,但是,那些希望能夠有很好移植行的程序應(yīng)該避免寫超 過 256 字節(jié)的正則表達(dá)式 ,因為 POSIX 兼容的實現(xiàn)可以拒絕接受這樣的正則表達(dá)式。
ARE 實際上和 POSIX ERE 不兼容的唯一的特性是在方括號表達(dá)式里\ 并不失去它特殊的含義。所有其它 ARE 特性都使用在 POSIX ERE 里面是非法或者是未定義、 未聲明效果的語法;引導(dǎo)符的***就是再 POSIX 的 BRE 和 ERE 之外的語法。
許多 ARE 擴(kuò)展都是從 Perl 那里拿來的,但是有些做了修改,去掉了, 以及一些 Perl 里沒有出現(xiàn)的擴(kuò)展。要注意的不兼容包括\b,\B,對結(jié)尾的換行 缺乏特別的處理,對那些換行敏感匹配的附加的補齊方括弧表達(dá)式,在前瞻約束里 對圓括號和方括號引用的限制,以及最長/最短匹配(而不是第一匹配)語義。
PostgreSQL 7.4 之前的版本里的 ARE 和 ERE 存在兩個非常顯然的不兼容:
在 ARE 里,后面跟著一個字母數(shù)字的\要么是一個逃逸,要么是錯誤,但是在以前的版本里, 它只是寫那個字母數(shù)字的另外一種方法。這個應(yīng)該不是什么問題,因為在以前的版本里沒有什么原因讓我們寫這樣的序列。
在 ARE 里\在[]里還是一個特殊字符, 因此在方括號表達(dá)式里的一個文本\必須寫成\\。
BRE 在幾個方面和 ERE 不太一樣。|,+,?都是普通字符,它們沒有等效的功能替換。 范圍的分隔符是\{和\},因為{和}本身是普通字符。 嵌套的子表達(dá)式的圓括號是\(和\),因為(和)自身是普通字符。 除非在正則表達(dá)式開頭或者是圓括號封裝的子表達(dá)式開頭,^都是普通字符, 除非在正則表達(dá)式結(jié)尾或者是圓括號封裝的子表達(dá)式的結(jié)尾,$是一個普通字符, 而如果*出現(xiàn)在正則表達(dá)式開頭或者是圓括號封裝的子表達(dá)式開頭(前面可能有^), 那么它是個普通字符。最后,可以用單數(shù)字的后引用,以及\<和\>分別 是[[:<:]]和[[:>:]]的同義詞;沒有其它的逃逸。