PostgreSQL
提供了三种独立的模式匹配方式:
传统的
SQL
LIKE
操作符、
较新的
SIMILAR TO
操作符
(在 SQL:1999
中加入),
以及
POSIX
风格的正则表达式。
除了基本的
“这个字符串是否匹配这个模式?”
操作符之外,
还有可用于提取或替换匹配子串、
以及在匹配位置拆分字符串的函数。
如果你的模式匹配需求超出了这里的内容, 可以考虑用 Perl 或 Tcl 编写一个用户定义的函数。
虽然大多数正则表达式搜索可以非常快地执行, 但也可能构造出需要任意多的时间和内存来处理的正则表达式。 要警惕从有敌意的来源接受正则表达式搜索模式。 如果必须这样做, 建议施加一条语句超时。
使用
SIMILAR TO
模式的搜索具有同样的安全隐患,
因为
SIMILAR TO
提供了许多与
POSIX
风格正则表达式相同的能力。
LIKE
搜索比其他两种选择简单得多,
在模式来源可能有敌意的情况下使用它更为安全。
SIMILAR TO 和
POSIX
风格的正则表达式不支持非确定性排序规则。
如果需要,
可以使用
LIKE,
或者对该表达式应用一个不同的排序规则,
来绕过这一限制。
LIKE #stringLIKEpattern[ESCAPEescape-character]stringNOT LIKEpattern[ESCAPEescape-character]
如果
string
匹配所提供的
pattern,
那么
LIKE
表达式返回真。
(正如预期的那样,
如果
LIKE
返回真,
则
NOT LIKE
表达式返回假,
反之亦然。
一个等价的表达式是
NOT (。)
string LIKE
pattern)
如果
pattern
不包含百分号或下划线,
那么该模式只表示字符串本身;
在这种情况下
LIKE
的行为就像等于操作符。
pattern
中的一个下划线
(_)
代表
(匹配)
任何单个字符;
一个百分号
(%)
匹配零个或更多字符的任何序列。
Some examples:
'abc' LIKE 'abc' true 'abc' LIKE 'a%' true 'abc' LIKE '_b_' true 'abc' LIKE 'c' false
LIKE
模式匹配支持非确定性排序规则
(参见
Section 23.2.2.4),
例如不区分大小写的排序规则,
或者忽略标点之类的排序规则。
因此在使用不区分大小写的排序规则时,
可以有:
'AbC' LIKE 'abc' COLLATE case_insensitive true 'AbC' LIKE 'a%' COLLATE case_insensitive true
对于忽略某些字符的排序规则, 或一般而言把不同长度的字符串视为相等的排序规则, 其语义会变得稍微复杂一些。 考虑这些例子:
'.foo.' LIKE 'foo' COLLATE ign_punct true '.foo.' LIKE 'f_o' COLLATE ign_punct true '.foo.' LIKE '_oo' COLLATE ign_punct false
匹配的工作方式是:
模式被划分为通配符和非通配符字符串的序列
(通配符是
_ 和
%)。
例如,
模式
f_o
被划分为
f, _, o,
模式
_oo
被划分为
_,
oo。
如果输入字符串能够被划分成这样:
通配符分别匹配一个字符或任意数量的字符,
而非通配符的部分在适用的排序规则下相等,
那么输入字符串就匹配该模式。
因此例如
'.foo.'
LIKE 'f_o' COLLATE ign_punct
为真,
因为可以把
.foo.
划分为
.f, o, o.,
然后
'.f' = 'f' COLLATE ign_punct、
'o'
匹配
_
通配符,
并且
'o.' = 'o' COLLATE
ign_punct。
但
'.foo.' LIKE '_oo' COLLATE
ign_punct
为假,
因为
.foo.
无法被划分为第一个字符是任意字符、
其余字符串与
oo
比较相等的形式。
(注意,
单字符通配符总是精确匹配一个字符,
与排序规则无关。
因此在这个例子中,
_
会匹配
.,
但这样输入字符串的其余部分就不会匹配模式的其余部分。)
LIKE
模式匹配总是覆盖整个字符串。
因此,
如果想要匹配一个字符串中任何位置的序列,
该模式必须以百分号开始和结束。
要匹配字面上的下划线或百分号而不匹配其他字符,
pattern
中的相应字符必须前面加上转义字符。
默认的转义字符是反斜杠,
但可以通过使用
ESCAPE
子句选择一个不同的字符。
要匹配转义字符本身,
写两个转义字符。
如果你关闭了 standard_conforming_strings, 那么你在字面字符串常量中写的任何反斜杠都需要写成双份。 更多信息请参见 Section 4.1.2.1。
也可以通过写
ESCAPE ''
来选择不使用转义字符。
这实际上禁用了转义机制,
使得无法关闭模式中下划线和百分号的特殊含义。
按照 SQL 标准,
省略
ESCAPE
意味着没有转义字符
(而不是默认为反斜杠),
并且不允许零长度的
ESCAPE
值。
因此
PostgreSQL
在这方面的行为略微偏离标准。
关键字 ILIKE
可以用来取代
LIKE,
使匹配根据当前活动的区域设置不区分大小写。
(但它不支持非确定性排序规则。)
它不属于
SQL
标准,
而是
PostgreSQL
的一个扩展。
操作符 ~~
等同于 LIKE,
而
~~*
对应于
ILIKE。
还有
!~~ 和
!~~*
操作符,
它们分别代表
NOT LIKE 和
NOT
ILIKE。
所有这些操作符都是
PostgreSQL
特有的。
你可能会在
EXPLAIN
输出和类似的地方看到这些操作符的名字,
因为解析器实际上会把
LIKE
等翻译为这些操作符。
短语 LIKE、
ILIKE、
NOT LIKE 和
NOT ILIKE
在
PostgreSQL
语法中通常被视为操作符;
例如它们可以用在
expression
operator ANY
(subquery)
构造中,
尽管那里不能包含
ESCAPE
子句。
在某些晦涩的情形下,
可能有必要改用底层的操作符名字。
另请参见以…开始操作符
^@
以及相应的
starts_with()
函数,
它们在只需要匹配一个字符串的开头时很有用。
SIMILAR TO 正则表达式 #stringSIMILAR TOpattern[ESCAPEescape-character]stringNOT SIMILAR TOpattern[ESCAPEescape-character]
SIMILAR TO
操作符根据它的模式是否匹配给定的字符串而返回真或假。
它类似于
LIKE,
不同之处在于它使用 SQL
标准对正则表达式的定义来解释模式。
SQL 正则表达式是
LIKE
记法与普通
(POSIX)
正则表达式记法之间的一个奇特混合体。
与 LIKE
一样,
只有当模式匹配整个字符串时,
SIMILAR TO
操作符才会成功;
这与普通正则表达式的行为不同,
在普通正则表达式中模式可以匹配字符串的任何部分。
与
LIKE
一样,
SIMILAR TO
使用
_ 和
%
作为通配符,
分别表示任何单个字符和任何字符串
(它们分别可比于 POSIX
正则表达式中的
. 和
.*)。
除了这些从
LIKE
借用的设施之外,
SIMILAR TO
还支持这些从 POSIX
正则表达式借用的模式匹配元字符:
|
表示二选一
(两个备选项之一)。
*
表示前一项重复零次或多次。
+
表示前一项重复一次或多次。
?
表示前一项重复零次或一次。
{m}
表示前一项恰好重复
m
次。
{m,}
表示前一项重复
m
次或更多次。
{m,n}
表示前一项至少重复
m
次、
且不超过
n
次。
圆括号
()
可以用来把若干项分组为一个单一的逻辑项。
一个方括号表达式
[...]
规定一个字符类,
正如在 POSIX
正则表达式中一样。
Notice that the period (.) is not a metacharacter
for SIMILAR TO.
与 LIKE
一样,
反斜杠会关闭这些元字符中任何一个的特殊含义。
可以用
ESCAPE
指定一个不同的转义字符,
或者可以通过写
ESCAPE ''
来禁用转义能力。
按照 SQL 标准,
省略
ESCAPE
意味着没有转义字符
(而不是默认为反斜杠),
并且不允许零长度的
ESCAPE
值。
因此
PostgreSQL
在这方面的行为略微偏离标准。
另一个非标准的扩展是: 在转义字符后面跟一个字母或数字, 可以访问为 POSIX 正则表达式定义的转义序列; 参见下文的 Table 9.20、 Table 9.21 和 Table 9.22。
Some examples:
'abc' SIMILAR TO 'abc' true 'abc' SIMILAR TO 'a' false 'abc' SIMILAR TO '%(b|d)%' true 'abc' SIMILAR TO '(b|c)%' false '-abc-' SIMILAR TO '%\mabc\M%' true 'xabcy' SIMILAR TO '%\mabc\M%' false
带有三个参数的
substring
函数提供了对一个匹配 SQL
正则表达式模式的子串的提取。
该函数可以按照标准 SQL
语法书写:
substring(stringsimilarpatternescapeescape-character)
或者使用现已过时的 SQL:1999 语法:
substring(stringfrompatternforescape-character)
或者作为一个普通的三参数函数:
substring(string,pattern,escape-character)
与 SIMILAR TO
一样,
指定的模式必须匹配整个数据字符串,
否则该函数失败并返回空。
为了指示模式中匹配到的数据子串令人感兴趣的那部分,
模式中应当包含两次转义字符后跟双引号
(")
的出现。
当匹配成功时,
返回与模式中这两个分隔符之间的部分相匹配的文本。
转义的双引号分隔符实际上把
substring
的模式划分成三个独立的正则表达式;
例如,
这三个部分中任何一部分里的竖线
(|)
只影响该部分。
此外,
当对数据字符串的多少与模式的哪个部分相匹配存在任何歧义时,
这三个正则表达式中的第一个和第三个被定义为匹配尽可能少的文本,
而非尽可能多的文本。
(用 POSIX
的行话来说,
第一个和第三个正则表达式被强制为非贪婪的。)
作为对 SQL 标准的扩展, PostgreSQL 允许只有一个转义的双引号分隔符, 在这种情况下第三个正则表达式被视为空; 或者没有分隔符, 在这种情况下第一个和第三个正则表达式被视为空。
一些例子,
其中
#"
是返回字符串的定界符:
substring('foobar' similar '%#"o_b#"%' escape '#') oob
substring('foobar' similar '#"o_b#"%' escape '#') NULL
Table 9.16 列出了使用 POSIX 正则表达式进行模式匹配的可用操作符。
Table 9.16. 正则表达式匹配操作符
操作符 说明 示例 |
|---|
字符串与正则表达式匹配, 区分大小写
|
字符串与正则表达式匹配, 不区分大小写
|
字符串与正则表达式不匹配, 区分大小写
|
字符串与正则表达式不匹配, 不区分大小写
|
POSIX
正则表达式提供了比
LIKE 和
SIMILAR TO
操作符更强大的模式匹配手段。
许多 Unix 工具,
例如 egrep、
sed 或
awk,
都使用一种与此处描述的相似的模式匹配语言。
正则表达式是一个字符序列,
它是一组字符串
(一个
正则集)
的缩写式定义。
如果一个字符串是该正则表达式所描述的正则集的成员,
就称它匹配该正则表达式。
与 LIKE
一样,
模式字符精确地匹配字符串字符,
除非它们是正则表达式语言中的特殊字符
— 但正则表达式使用的特殊字符与
LIKE
的不同。
与
LIKE
模式不同,
正则表达式允许匹配字符串内的任何位置,
除非该正则表达式被显式地锚定在字符串的开头或结尾。
Some examples:
'abcd' ~ 'bc' true 'abcd' ~ 'a.c' true — dot matches any character 'abcd' ~ 'a.*d' true —*repeats the preceding pattern item 'abcd' ~ '(b|x)' true —|means OR, parentheses group 'abcd' ~ '^a' true —^anchors to start of string 'abcd' ~ '^(b|c)' false — would match except for anchoring
POSIX 模式语言将在下文详细得多地描述。
带有两个参数的
substring
函数,
即
substring(,
提供对一个匹配 POSIX
正则表达式模式的子串的提取。
如果没有匹配,
它返回空;
否则返回与该模式相匹配的第一部分文本。
但如果模式中包含任何圆括号,
那么返回的是与第一个带圆括号的子表达式
(即左圆括号在最前的那个)
相匹配的那部分文本。
如果你想在表达式中使用圆括号而又不触发这个例外,
可以把整个表达式都放进圆括号里。
如果你需要在模式中、
在想提取的子表达式之前使用圆括号,
请参见下文描述的非捕获圆括号。
string from
pattern)
Some examples:
substring('foobar' from 'o.b') oob
substring('foobar' from 'o(.)b') o
regexp_count
函数统计一个 POSIX
正则表达式模式与一个字符串匹配的位置的数量。
它的语法是
regexp_count(string,
pattern
[, start
[, flags
]])。
在
string
中搜索
pattern,
通常从字符串的开头开始,
但如果提供了
start
参数,
则从那个字符索引开始。
flags
参数是一个可选的文本字符串,
包含零个或多个改变该函数行为的单字母标志。
例如,
在
flags
中包含
i
表示不区分大小写的匹配。
受支持的标志在
Table 9.24
中描述。
Some examples:
regexp_count('ABCABCAXYaxy', 'A.') 3
regexp_count('ABCABCAXYaxy', 'A.', 1, 'i') 4
regexp_instr
函数返回 POSIX 正则表达式模式与一个字符串的第
N
次匹配的起始或结束位置,
如果没有这样的匹配则返回零。
它的语法是
regexp_instr(string,
pattern
[, start
[, N
[, endoption
[, flags
[, subexpr
]]]]])。
在
string
中搜索
pattern,
通常从字符串的开头开始,
但如果提供了
start
参数,
则从那个字符索引开始。
如果指定了
N,
则定位该模式的第
N
次匹配,
否则定位第一次匹配。
如果省略了
endoption
参数,
或者把它指定为零,
该函数返回匹配的第一个字符的位置。
否则,
endoption
必须为 1,
该函数返回匹配之后的那个字符的位置。
flags
参数是一个可选的文本字符串,
包含零个或多个改变该函数行为的单字母标志。
受支持的标志在
Table 9.24
中描述。
对于一个包含带圆括号的子表达式的模式,
subexpr
是一个整数,
指示哪个子表达式令人感兴趣:
结果标识与那个子表达式相匹配的子串的位置。
子表达式按照它们的前导圆括号的顺序编号。
当省略了
subexpr
或它为零时,
结果标识整个匹配的位置,
而不管带圆括号的子表达式。
Some examples:
regexp_instr('number of your street, town zip, FR', '[^,]+', 1, 2)
23
regexp_instr(string=>'ABCDEFGHI', pattern=>'(c..)(...)', start=>1, "N"=>1, endoption=>0, flags=>'i', subexpr=>2)
6
regexp_like
函数检查一个 POSIX
正则表达式模式的匹配是否出现在一个字符串中,
返回布尔值真或假。
它的语法是
regexp_like(string,
pattern
[, flags ])。
flags
参数是一个可选的文本字符串,
包含零个或多个改变该函数行为的单字母标志。
受支持的标志在
Table 9.24
中描述。
如果没有指定任何标志,
这个函数的结果与
~
操作符相同。
如果只指定了
i
标志,
则结果与
~*
操作符相同。
Some examples:
regexp_like('Hello World', 'world') false
regexp_like('Hello World', 'world', 'i') true
regexp_match
函数返回一个文本数组,
其中包含 POSIX
正则表达式模式与一个字符串的第一次匹配之内的匹配子串。
它的语法是
regexp_match(string,
pattern [, flags ])。
如果没有匹配,
结果为
NULL。
如果找到了一个匹配,
并且
pattern
不包含带圆括号的子表达式,
那么结果是一个单元素文本数组,
其中包含与整个模式相匹配的子串。
如果找到了一个匹配,
并且
pattern
包含带圆括号的子表达式,
那么结果是一个文本数组,
其第
n
个元素是与
pattern
的第
n
个带圆括号的子表达式相匹配的子串
(不包括
“非捕获”圆括号;
细节见下文)。
flags
参数是一个可选的文本字符串,
包含零个或多个改变该函数行为的单字母标志。
受支持的标志在
Table 9.24
中描述。
Some examples:
SELECT regexp_match('foobarbequebaz', 'bar.*que');
regexp_match
--------------
{barbeque}
(1 row)
SELECT regexp_match('foobarbequebaz', '(bar)(beque)');
regexp_match
--------------
{bar,beque}
(1 row)
在你只想要整个匹配子串、
没有匹配则要
NULL
的常见情形下,
最好的解决方案是使用
regexp_substr()。
然而,
regexp_substr()
只存在于
PostgreSQL
版本 15 及更高版本中。
在更旧的版本中工作时,
你可以提取
regexp_match()
结果的第一个元素,
例如:
SELECT (regexp_match('foobarbequebaz', 'bar.*que'))[1];
regexp_match
--------------
barbeque
(1 row)
regexp_matches
函数返回一组文本数组,
其中包含 POSIX
正则表达式模式与一个字符串的匹配之内的匹配子串。
它的语法与
regexp_match
相同。
如果没有匹配,
这个函数不返回任何行;
如果有一个匹配且未给出
g
标志,
则返回一行;
如果有
N
个匹配且给出了
g
标志,
则返回
N
行。
每个被返回的行都是一个文本数组,
其中包含完整的匹配子串,
或与
pattern
中带圆括号的子表达式相匹配的子串,
正如上文针对
regexp_match
描述的那样。
regexp_matches
接受
Table 9.24
中展示的所有标志,
外加
g
标志,
它命令该函数返回所有匹配,
而非只是第一个。
Some examples:
SELECT regexp_matches('foo', 'not there');
regexp_matches
----------------
(0 rows)
SELECT regexp_matches('foobarbequebazilbarfbonk', '(b[^b]+)(b[^b]+)', 'g');
regexp_matches
----------------
{bar,beque}
{bazil,barf}
(2 rows)
在大多数情况下,
regexp_matches()
应当与
g
标志一起使用,
因为如果你只想要第一次匹配,
使用
regexp_match()
更简单也更高效。
然而,
regexp_match()
只存在于
PostgreSQL
版本 10 及更高版本中。
在更旧的版本中工作时,
一个常见技巧是把一次
regexp_matches()
调用放在一个子选择中,
例如:
SELECT col1, (SELECT regexp_matches(col2, '(bar)(beque)')) FROM tab;
如果有匹配,
这会产生一个文本数组,
否则产生
NULL,
与
regexp_match()
会做的一样。
如果没有这个子选择,
那么对于没有匹配的表行,
这条查询根本不会产生任何输出,
这通常不是想要的行为。
regexp_replace
函数提供把新文本替换到与 POSIX
正则表达式模式相匹配的子串中的能力。
它的语法是
regexp_replace(string,
pattern, replacement
[, flags ])
或
regexp_replace(string,
pattern, replacement,
start
[, N
[, flags ]])。
如果没有与
pattern
相匹配的内容,
源
string
原样返回。
如果有匹配,
返回的
string
中与匹配子串对应的位置会被替换为
replacement
字符串。
replacement
字符串可以包含
\n,
其中
n
是 1 到 9,
表示应当插入与模式的第
n
个带圆括号的子表达式相匹配的源子串;
它还可以包含
\&,
表示应当插入与整个模式相匹配的子串。
如果你需要在替换文本中放入一个字面上的反斜杠,
写
\\。
在
string
中搜索
pattern,
通常从字符串的开头开始,
但如果提供了
start
参数,
则从那个字符索引开始。
默认情况下,
只替换模式的第一次匹配。
如果指定了
N
并且它大于零,
则替换该模式的第
N
次匹配。
如果给出了
g
标志,
或者指定了
N
并且它为零,
则替换
start
位置上及之后的所有匹配。
(当指定了
N
时,
g
标志会被忽略。)
flags
参数是一个可选的文本字符串,
包含零个或多个改变该函数行为的单字母标志。
受支持的标志
(但不含
g)
在
Table 9.24
中描述。
Some examples:
regexp_replace('foobarbaz', 'b..', 'X')
fooXbaz
regexp_replace('foobarbaz', 'b..', 'X', 'g')
fooXX
regexp_replace('foobarbaz', 'b(..)', 'X\1Y', 'g')
fooXarYXazY
regexp_replace('A PostgreSQL function', 'a|e|i|o|u', 'X', 1, 0, 'i')
X PXstgrXSQL fXnctXXn
regexp_replace(string=>'A PostgreSQL function', pattern=>'a|e|i|o|u', replacement=>'X', start=>1, "N"=>3, flags=>'i')
A PostgrXSQL function
regexp_split_to_table
函数使用一个 POSIX
正则表达式模式作为分隔符来拆分一个字符串。
它的语法是
regexp_split_to_table(string, pattern
[, flags ])。
如果没有与
pattern
相匹配的内容,
该函数返回
string。
如果至少有一个匹配,
对每个匹配,
它返回从上一次匹配的结束
(或字符串的开头)
到本次匹配的开头之间的文本。
当不再有匹配时,
它返回从最后一次匹配的结束到字符串结尾之间的文本。
flags
参数是一个可选的文本字符串,
包含零个或多个改变该函数行为的单字母标志。
regexp_split_to_table
支持
Table 9.24
中描述的标志。
regexp_split_to_array
函数的行为与
regexp_split_to_table
相同,
只是
regexp_split_to_array
把它的结果作为一个
text
数组返回。
它的语法是
regexp_split_to_array(string, pattern
[, flags ])。
参数与
regexp_split_to_table
的相同。
Some examples:
SELECT foo FROM regexp_split_to_table('the quick brown fox jumps over the lazy dog', '\s+') AS foo;
foo
-------
the
quick
brown
fox
jumps
over
the
lazy
dog
(9 rows)
SELECT regexp_split_to_array('the quick brown fox jumps over the lazy dog', '\s+');
regexp_split_to_array
-----------------------------------------------
{the,quick,brown,fox,jumps,over,the,lazy,dog}
(1 row)
SELECT foo FROM regexp_split_to_table('the quick brown fox', '\s*') AS foo;
foo
-----
t
h
e
q
u
i
c
k
b
r
o
w
n
f
o
x
(16 rows)
正如最后一个例子所演示的, 正则表达式拆分函数会忽略发生在字符串开头或结尾、 或者紧跟在上一次匹配之后的零长度匹配。 这与其他正则表达式函数所实现的正则表达式匹配的严格定义相反, 但它通常是实践中最方便的行为。 其他软件系统(例如 Perl) 也使用类似的定义。
regexp_substr
函数返回与一个 POSIX
正则表达式模式相匹配的子串,
如果没有匹配则返回
NULL。
它的语法是
regexp_substr(string,
pattern
[, start
[, N
[, flags
[, subexpr
]]]])。
在
string
中搜索
pattern,
通常从字符串的开头开始,
但如果提供了
start
参数,
则从那个字符索引开始。
如果指定了
N,
则返回该模式的第
N
次匹配,
否则返回第一次匹配。
flags
参数是一个可选的文本字符串,
包含零个或多个改变该函数行为的单字母标志。
受支持的标志在
Table 9.24
中描述。
对于一个包含带圆括号的子表达式的模式,
subexpr
是一个整数,
指示哪个子表达式令人感兴趣:
结果是与那个子表达式相匹配的子串。
子表达式按照它们的前导圆括号的顺序编号。
当省略了
subexpr
或它为零时,
结果是整个匹配,
而不管带圆括号的子表达式。
Some examples:
regexp_substr('number of your street, town zip, FR', '[^,]+', 1, 2)
town zip
regexp_substr('ABCDEFGHI', '(c..)(...)', 1, 1, 'i', 2)
FGH
PostgreSQL 的正则表达式是用 Henry Spencer 编写的一个软件包实现的。 下文对正则表达式的许多描述都逐字复制自他的手册。
在 POSIX 1003.2
中定义的正则表达式
(RE)
有两种形式:
扩展的
RE
或 ERE
(大致就是
egrep
的那些),
以及
基本的
RE
或 BRE
(大致就是
ed
的那些)。
PostgreSQL
两种形式都支持,
并且还实现了一些 POSIX
标准中没有、
但由于在 Perl 和 Tcl
之类的编程语言中可用而被广泛使用的扩展。
在本文档中,
使用这些非 POSIX
扩展的
RE
被称为
高级的
RE
或 ARE。
ARE 几乎是 ERE
的精确超集,
但 BRE
存在若干记法上的不兼容之处
(而且功能受限得多)。
我们首先描述 ARE 和 ERE
的形式,
并指出只适用于 ARE
的特性,
然后描述 BRE
的差异。
PostgreSQL 总是先假定一个正则表达式遵循 ARE 规则。 然而, 可以通过向 RE 模式前置一个 嵌入式选项 来选择受限得多的 ERE 或 BRE 规则, 如 Section 9.7.3.4 中所描述。 这对于期望恰好遵循 POSIX 1003.2 规则的应用程序实现兼容性可能有用。
一个正则表达式被定义为一个或多个
分支,
分支之间用
|
分隔。
它匹配任何与其中某个分支相匹配的东西。
一个分支是零个或多个被连接起来的 被量化的原子或 约束。 它先匹配第一个的匹配, 再接着匹配第二个的匹配,依此类推; 一个空分支匹配空字符串。
一个被量化的原子是一个 原子, 后面可能跟一个单一的 量词。 没有量词时, 它匹配该原子的一个匹配。 带有量词时, 它可以匹配该原子的某个数量的匹配。 一个 原子 可以是 Table 9.17 中展示的任何一种可能。 可能的量词及其含义展示在 Table 9.18 中。
一个 约束 匹配一个空字符串, 但只在满足特定条件时才匹配。 约束可以用在可以使用原子的地方, 只是它后面不能跟量词。 简单的约束展示在 Table 9.19 中; 还有一些别的约束将在后文描述。
Table 9.17. 正则表达式原子
| Atom | 说明 |
|---|---|
(re) | (其中 re 是任何正则表达式)
匹配对 re 的一次匹配,
并记录该匹配以便可能的报告 |
(?:re) | 同上,但该匹配不会被记录以便报告(一组“非捕获”圆括号)(仅限 ARE) |
. | 匹配任何单个字符 |
[chars] | 一个方括号表达式,匹配 chars 中的任意一个字符(详见 Section 9.7.3.2) |
\k | (其中 k 是一个非字母数字字符)匹配被当作普通字符的该字符,例如 \\ 匹配一个反斜杠字符 |
\c | 其中 c 是字母数字字符(后面可能跟其他字符)时是一个转义,参见 Section 9.7.3.3(仅限 ARE;在 ERE 和 BRE 中,它匹配 c) |
{ | 当后面跟的不是数字时,匹配左花括号字符 {;当后面跟的是数字时,它是一个界限的开始(见下文) |
x | 其中 x 是一个没有其他特殊意义的单一字符,
匹配该字符 |
一个 RE
不能以反斜杠
(\)
结尾。
如果你关闭了 standard_conforming_strings, 那么你在字面字符串常量中写的任何反斜杠都需要写成双份。 更多信息请参见 Section 4.1.2.1。
Table 9.18. 正则表达式量词
| 量词 | 匹配 |
|---|---|
* | 该原子的零次或多次匹配的序列 |
+ | 该原子的一次或多次匹配的序列 |
? | 该原子的零次或一次匹配的序列 |
{m} | 该原子的恰好 m 次匹配的序列 |
{m,} | 该原子的 m 次或更多次匹配的序列 |
{m,n} | 该原子的 m 到 n 次(含)匹配的序列;m 不能超过 n |
*? | * 的非贪婪版本 |
+? | + 的非贪婪版本 |
?? | ? 的非贪婪版本 |
{m}? | {m} 的非贪婪版本 |
{m,}? | {m,} 的非贪婪版本 |
{m,n}? | {m,n} 的非贪婪版本 |
使用
{...}
的形式被称为
界限。
界限之内的数字
m 和
n
是无符号十进制整数,
允许的取值从 0 到
255(含)。
非贪婪量词 (只在 ARE 中可用) 与其对应的正常 (贪婪) 版本匹配相同的可能性, 但倾向于最小数量的匹配而非最大数量。 更多细节请参见 Section 9.7.3.5。
一个量词不能紧跟在另一个量词之后,
例如
**
是无效的。
一个量词不能开始一个表达式或子表达式,
也不能跟在
^ 或
|
之后。
Table 9.19. 正则表达式约束
| 约束 | 说明 |
|---|---|
^ | 在字符串的开头匹配 |
$ | 在字符串的结尾匹配 |
(?=re) | 正向前向查找在任何一个匹配 re 的子串开始的位置匹配(仅限 ARE) |
(?!re) | 负向前向查找在任何没有匹配 re 的子串开始的位置匹配(仅限 ARE) |
(?<=re) | 正向后向查找在任何一个匹配 re 的子串结束的位置匹配(仅限 ARE) |
(?<!re) | 负向后向查找在任何没有匹配 re 的子串结束的位置匹配(仅限 ARE) |
前向查找和后向查找约束不能包含 反向引用 (参见 Section 9.7.3.3), 并且它们之中的所有圆括号都被视为非捕获的。
一个
方括号表达式
是一个由
[]
括起来的字符列表。
它通常匹配列表中的任何单个字符
(但见下文)。
如果列表以
^
开头,
它匹配任何
不在该列表其余部分中的单个字符。
如果列表中的两个字符用
-
分隔,
那么它是排序序列中这两个字符之间
(含)
的完整字符范围的简写,
例如
ASCII
中的
[0-9]
匹配任何十进制数字。
两个范围共享一个端点是非法的,
例如
a-c-e。
范围非常依赖于排序序列,
因此可移植的程序应当避免依赖它们。
要把一个字面上的
]
包含在列表中,
让它成为第一个字符
(如果使用了
^,
则在其之后)。
要包含一个字面上的
-,
让它成为第一个或最后一个字符,
或者一个范围的第二个端点。
要把一个字面上的
-
用作一个范围的第一个端点,
请把它括在
[. 和
.]
之中使它成为一个排序元素
(见下文)。
除了这些字符、
一些使用
[
的组合
(见接下来的段落)
以及转义
(仅限 ARE)
之外,
所有其他特殊字符在方括号表达式内都会失去其特殊意义。
特别是,
当遵循 ERE 或 BRE
规则时,
\
并不特殊,
尽管在 ARE
中它是特殊的
(作为引入一个转义)。
在方括号表达式内,
一个被括在
[. 和
.]
之中的排序元素
(一个字符、
一个在排序时被当作单个字符的多字符序列、
或其中之一的排序序列名字)
代表那个排序元素的字符序列。
该序列被视为方括号表达式列表中的单个元素。
这允许一个包含多字符排序元素的方括号表达式匹配多于一个的字符,
例如,
如果排序序列包含一个
ch
排序元素,
那么 RE
[[.ch.]]*c
匹配
chchcc
的前五个字符。
PostgreSQL 目前不支持多字符排序元素。 这里的信息描述的是可能的未来行为。
在方括号表达式内,
一个被括在
[= 和
=]
之中的排序元素是一个
等价类,
它代表与那个排序元素等价的所有排序元素
(包括它自身)
的字符序列。
(如果没有其他等价的排序元素,
那么它的处理方式就如同外层的定界符是
[. 和
.]
一样。)
例如,
如果
o 和
^
是一个等价类的成员,
那么
[[=o=]]、
[[=^=]] 和
[o^]
全都是同义词。
等价类不能是一个范围的端点。
在方括号表达式内,
一个被括在
[: 和
:]
之中的字符类名字代表属于那个类的所有字符的列表。
字符类不能被用作范围的端点。
POSIX
标准定义了这些字符类名字:
alnum
(字母和数字)、
alpha
(字母)、
blank
(空格和制表符)、
cntrl
(控制字符)、
digit
(数字)、
graph
(除空格之外的可打印字符)、
lower
(小写字母)、
print
(包括空格在内的可打印字符)、
punct
(标点)、
space
(任何空白)、
upper
(大写字母),
以及
xdigit
(十六进制数字)。
对于 7 位 ASCII
集中的字符,
这些标准字符类的行为在各平台上通常是一致的。
一个给定的非 ASCII
字符是否被认为属于这些类中的某一个,
取决于正则表达式函数或操作符所使用的
排序规则
(参见
Section 23.2),
默认情况下则取决于数据库的
LC_CTYPE
区域设置
(参见
Section 23.1)。
即使在名称相似的区域设置中,
非 ASCII
字符的归类也可能因平台而异。
(但
C
区域设置从不认为任何非 ASCII
字符属于这些类中的任何一个。)
除了这些标准字符类之外,
PostgreSQL
还定义了
word
字符类,
它等同于
alnum
加上下划线
(_)
字符;
还定义了
ascii
字符类,
它恰好包含 7 位 ASCII
集。
方括号表达式有两种特殊情形:
方括号表达式
[[:<:]] 和
[[:>:]]
是约束,
分别匹配单词开头和结尾的空字符串。
单词被定义为一个由单词字符构成的序列,
其前面和后面都不是单词字符。
单词字符是属于
word
字符类的任何字符,
即任何字母、数字或下划线。
这是一个扩展,
它与
POSIX 1003.2
兼容但未被它规定,
在打算移植到其他系统的软件中应当谨慎使用。
下文描述的约束转义通常更可取;
它们同样不标准,
但更容易输入。
转义
是以
\
开头并后跟一个字母数字字符的特殊序列。
转义有几种变体:
字符项转义、
类简写、
约束转义和反向引用。
在 ARE 中,
一个
\
后跟一个字母数字字符但不构成有效转义是非法的。
在 ERE 中没有转义:
在方括号表达式之外,
一个
\
后跟一个字母数字字符只是把那个字符当作普通字符;
而在方括号表达式之内,
\
是一个普通字符。
(后者是 ERE 与 ARE
之间唯一真正的区别。)
字符项转义 的存在是为了便于在 RE 中指定不可打印字符和其他不便使用的字符。 它们展示在 Table 9.20 中。
类简写转义 为某些常用的字符类提供了简写形式。 它们展示在 Table 9.21 中。
一个 约束转义 是一个约束, 以转义的形式书写, 在满足特定条件时匹配空字符串。 它们展示在 Table 9.22 中。
一个
反向引用
(\n)
匹配由数字
n
指定的先前带圆括号的子表达式所匹配的相同字符串
(参见
Table 9.23)。
例如,
([bc])\1
匹配
bb 或
cc,
但不匹配
bc 或
cb。
子表达式必须在 RE
中完全位于反向引用之前。
子表达式按照它们的前导圆括号的顺序编号。
非捕获圆括号不定义子表达式。
反向引用只考虑被引用子表达式所匹配的字符串字符,
而不考虑它包含的任何约束。
例如,
(^\d)\1
将匹配
22。
Table 9.20. 正则表达式字符项转义
| 转义 | 说明 |
|---|---|
\a | 告警(响铃)字符,如同 C 中那样 |
\b | 退格符,如同 C 中那样 |
\B | 反斜杠(\)的同义词,用于减少反斜杠加倍的需要 |
\cX | (其中 X 是任意字符)
低 5 位与 X 相同、
其他位全为零的那个字符 |
\e | 排序序列名为 ESC 的字符,如果没有这样的字符,则为八进制值 033 的字符 |
\f | 换页符,如同 C 中那样 |
\n | 换行符,如同 C 中那样 |
\r | 回车符,如同 C 中那样 |
\t | 水平制表符,如同 C 中那样 |
\uwxyz | (其中 wxyz 正好是四个十六进制数字)十六进制值为 0xwxyz 的字符 |
\Ustuvwxyz | (其中 stuvwxyz 正好是八个十六进制数字)十六进制值为 0xstuvwxyz 的字符 |
\v | 垂直制表符,如同 C 中那样 |
\xhhh | (其中 hhh 是任意的十六进制数字序列)十六进制值为 0xhhh 的字符(无论使用多少个十六进制数字,都表示一个单一字符) |
\0 | 值为 0 的那个字符(空字节) |
\xy | (其中 xy 正好是两个八进制数字,并且不是一个反向引用)八进制值为 0xy 的字符 |
\xyz | (其中 xyz 正好是三个八进制数字,并且不是一个反向引用)八进制值为 0xyz 的字符 |
十六进制数字是
0-9、
a-f
和
A-F。
八进制数字是
0-7。
指定了 ASCII
范围
(0–127)
之外的值的数字字符项转义,
其含义取决于数据库编码。
当编码为 UTF-8
时,
转义值等同于 Unicode
码点,
例如
\u1234
表示字符
U+1234。
对于其他多字节编码,
字符项转义通常只是指定该字符的字节值的串接。
如果转义值不对应于数据库编码中的任何合法字符,
不会抛出错误,
但它永远匹配不到任何数据。
字符项转义总是被当作普通字符。
例如,
\135
在 ASCII
中是
],
但
\135
不会终止一个方括号表达式。
Table 9.21. 正则表达式类简写转义
| 转义 | 说明 |
|---|---|
\d | 匹配任何数字,如同 [[:digit:]] |
\s | 匹配任何空白字符,如同 [[:space:]] |
\w | 匹配任何单词字符,如同 [[:word:]] |
\D | 匹配任何非数字,如同 [^[:digit:]] |
\S | 匹配任何非空白字符,如同 [^[:space:]] |
\W | 匹配任何非单词字符,如同 [^[:word:]] |
类简写转义也可以在方括号表达式内工作,
尽管上面展示的定义在那个上下文中在语法上并不完全有效。
例如,
[a-c\d]
等同于
[a-c[:digit:]]。
Table 9.22. 正则表达式约束转义
| 转义 | 说明 |
|---|---|
\A | 只在字符串的开头匹配(它与 ^ 的区别参见 Section 9.7.3.5) |
\m | 只在一个单词的开头匹配 |
\M | 只在一个单词的结尾匹配 |
\y | 只在一个单词的开头或结尾匹配 |
\Y | 只在一个既不是单词开头也不是单词结尾的位置匹配 |
\Z | 只在字符串的结尾匹配(它与 $ 的区别参见 Section 9.7.3.5) |
单词的定义与上文针对
[[:<:]] 和
[[:>:]]
给出的相同。
约束转义在方括号表达式内是非法的。
Table 9.23. 正则表达式反向引用
| 转义 | 说明 |
|---|---|
\m | (其中 m 是一个非零数字)对第 m 个子表达式的反向引用 |
\mnn | (其中 m 是一个非零数字,nn 是更多的数字,并且十进制值 mnn 不大于到目前为止已出现的捕获圆括号的数量)对第 mnn 个子表达式的反向引用 |
八进制字符项转义与反向引用之间存在固有的歧义, 如上文所提示的, 它通过以下启发式规则来解决。 一个前导零总是指示一个八进制转义。 一个后面没有跟其他数字的单一非零数字, 总是被当作一个反向引用。 一个不以零开头的多位数字序列, 如果它出现在一个合适的子表达式之后 (即该数字处于反向引用的合法范围内), 则被当作反向引用, 否则被当作八进制。
除了上面描述的主语法之外, 还有一些特殊形式和杂项语法设施可用。
一个 RE
可以以两种特殊的
指示符前缀之一开始。
如果一个 RE
以 ***:
开头,
那么 RE
的其余部分被视为一个 ARE。
(这在
PostgreSQL
中通常没有效果,
因为 RE
被假定就是 ARE;
但如果已经通过正则函数的
flags
参数指定了 ERE 或 BRE
模式,
它就会有效果。)
如果一个 RE
以 ***=
开头,
那么 RE
的其余部分被视为一个字面字符串,
所有字符都被当作普通字符。
一个 ARE
可以以
嵌入式选项开始:
一个序列
(?xyz)
(其中
xyz
是一个或多个字母字符)
指定影响 RE
其余部分的选项。
这些选项会覆盖任何先前确定的选项
— 特别是,
它们可以覆盖正则操作符所隐含的大小写敏感行为,
或者正则函数的
flags
参数。
可用的选项字母展示在
Table 9.24
中。
注意,
这些相同的选项字母也用在正则函数的
flags
参数中。
Table 9.24. 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
的结尾)
之间的所有字符同样会被忽略。
这允许对一个复杂的 RE
进行分段和注释。
这条基本规则有三个例外:
前面带有
\
的空白字符或
#
会被保留
方括号表达式内的空白或
#
会被保留
空白和注释不能出现在多字符符号之内,
例如
(?:
就此而言,空白字符指空格、制表符、换行符,
以及属于 space 字符类的任何字符。
最后,
在一个 ARE 中、
在方括号表达式之外,
序列
(?#ttt)
(其中
ttt
是任何不包含
)
的文本)
是一条注释,
会被完全忽略。
再强调一次,
这样的注释也不允许出现在多字符符号的字符之间,
例如
(?:。
这类注释更像一个历史产物,
而非一个有用的设施,
它们的使用已被弃用;
请改用展开语法。
如果开头的
***=
指示符已指定把用户的输入当作字面字符串而非 RE
来处理,
那么这些元语法扩展
一个都不可用。
如果一个 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
是非贪婪的,
因为
Y*?
是非贪婪的。
它可以从
Y
开始匹配,
并且匹配从那里开始的最短可能字符串,
即
Y1。
子表达式
[0-9]{1,3}
是贪婪的,
但它无法改变关于整体匹配长度的决定;
因此它被迫只匹配
1。
简而言之, 当一个 RE 同时包含贪婪与非贪婪的子表达式时, 总的匹配长度要么尽可能长, 要么尽可能短, 取决于分配给整个 RE 的属性。 分配给子表达式的属性只影响相对于彼此, 它们被允许 “吃掉” 这次匹配中的多少。
量词 {1,1} 和
{1,1}?
可以分别用来强制一个子表达式或整个 RE
具有贪婪性或非贪婪性。
当你需要整个 RE
具有与其元素所推断出的不同的贪婪性属性时,
这很有用。
例如,
假设我们正在尝试把一个包含一些数字的字符串划分为这些数字,
以及它们之前和之后的部分。
我们可能尝试这样做:
SELECT regexp_match('abc01234xyz', '(.*)(\d+)(.*)');
Result: {abc0123,4,xyz}
那样没有起作用:
第一个
.*
是贪婪的,
所以它
“吃掉”
尽可能多的内容,
把
\d+
留到最后一个可能的位置
(最后一位数字)上匹配。
我们可能尝试通过让它变为非贪婪来修复这个问题:
SELECT regexp_match('abc01234xyz', '(.*?)(\d+)(.*)');
Result: {abc,0,""}
那样也没有起作用, 因为现在整个 RE 是非贪婪的, 因此它会尽快结束整体的匹配。 我们可以通过强制整个 RE 为贪婪来得到想要的东西:
SELECT regexp_match('abc01234xyz', '(?:(.*?)(\d+)(.*)){1,1}');
Result: {abc,01234,xyz}
把 RE 的整体贪婪性与其各组成部分的贪婪性分开控制, 为处理变长模式提供了极大的灵活性。
在判断什么是更长或更短的匹配时,
匹配长度以字符而非排序元素来度量。
一个空字符串被认为比完全没有匹配更长。
例如:
bb*
匹配
abbbc
中间的三个字符;
(week|wee)(night|knights)
匹配
weeknights
的全部十个字符;
当把
(.*).*
与
abc
相匹配时,
带圆括号的子表达式匹配全部三个字符;
而当把
(a*)*
与
bc
相匹配时,
整个 RE
和带圆括号的子表达式都匹配一个空字符串。
如果指定了不区分大小写的匹配,
其效果很像是所有大小写区别都从字母表中消失了。
当一个以多种大小写形式存在的字母作为方括号表达式之外的普通字符
出现时,
它实际上被转换成一个同时包含两种大小写形式的方括号表达式,
例如
x
变成
[xX]。
当它出现在方括号表达式之内时,
它的所有大小写对应形式都会被加入该方括号表达式,
例如
[x]
变成
[xX],
而
[^x]
变成
[^xX]。
如果指定了换行敏感的匹配,
那么
.
以及使用
^
的方括号表达式永远不会匹配换行字符
(这样匹配就不会跨行,
除非 RE
显式地包含一个换行),
而
^ 和
$
除了分别在字符串的开头和结尾匹配之外,
还会分别匹配换行之后和之前的空字符串。
但 ARE 的转义
\A 和
\Z
仍然只匹配字符串的开头或结尾。
此外,
字符类简写
\D 和
\W
无论在这种模式下如何都会匹配换行。
(在
PostgreSQL 14
之前,
它们在换行敏感模式下不匹配换行。
写 [^[:digit:]]
或
[^[:word:]]
可以得到旧的行为。)
如果指定了部分换行敏感的匹配,
它对
.
和方括号表达式的影响与换行敏感匹配相同,
但对
^ 和
$
没有影响。
如果指定了反向部分换行敏感的匹配,
它对
^ 和
$
的影响与换行敏感匹配相同,
但对
.
和方括号表达式没有影响。
这没有太大用处,
提供它只是为了对称。
在这个实现中, 没有对 RE 的长度施加任何特定的限制。 然而, 打算高度可移植的程序不应当使用长于 256 字节的 RE, 因为一个符合 POSIX 的实现可以拒绝接受这样的 RE。
ARE 中真正与 POSIX ERE
不兼容的唯一特性是:
\
在方括号表达式内不失去它的特殊意义。
所有其他 ARE
特性使用的语法在 POSIX ERE
中要么是非法的,
要么有未定义或未指明的效果;
指示符的
***
语法同样超出了 POSIX
对 BRE 和 ERE
的语法。
许多 ARE
的扩展是从 Perl
借来的,
但其中一些为了清理而被更改,
还有少数 Perl
扩展不存在。
值得注意的不兼容之处包括
\b、
\B、
对尾部换行缺乏特殊处理、
把取反的方括号表达式加入受换行敏感匹配影响的对象、
对前向/后向查找约束中的圆括号和反向引用的限制,
以及最长/最短匹配
(而非第一次匹配)
的匹配语义。
BRE 在几个方面与 ERE
不同。
在 BRE 中,
|、
+ 和
?
是普通字符,
并且没有与它们的功能等价的东西。
界限的定界符是
\{ 和
\},
而
{ 和
}
单独出现时是普通字符。
用于嵌套子表达式的圆括号是
\( 和
\),
而
( 和
)
单独出现时是普通字符。
^
是普通字符,
除非出现在 RE
的开头或一个带圆括号的子表达式的开头;
$
是普通字符,
除非出现在 RE
的结尾或一个带圆括号的子表达式的结尾;
而
*
如果出现在 RE
的开头或一个带圆括号的子表达式的开头
(在一个可能的前导
^
之后),
则是普通字符。
最后,
单数字的反向引用可用,
并且
\< 和
\>
分别是
[[:<:]] 和
[[:>:]]
的同义词;
BRE 中没有其他转义可用。
从 SQL:2008 起, SQL 标准包含了按照 XQuery 正则表达式标准执行模式匹配的正则表达式操作符和函数:
LIKE_REGEX
OCCURRENCES_REGEX
POSITION_REGEX
SUBSTRING_REGEX
TRANSLATE_REGEX
PostgreSQL 目前没有实现这些操作符和函数。 每种情况下都可以获得如 Table 9.25 所示的大致等价的功能。 (表中两侧的各种可选子句已被省略。)
Table 9.25. 正则表达式函数等价形式
| SQL 标准 | PostgreSQL |
|---|---|
| regexp_like( or |
OCCURRENCES_REGEX( | regexp_count( |
POSITION_REGEX( | regexp_instr( |
SUBSTRING_REGEX( | regexp_substr( |
TRANSLATE_REGEX( | regexp_replace( |
与 PostgreSQL 提供的正则表达式函数类似的正则表达式函数, 在许多其他 SQL 实现中也可用, 而 SQL 标准的函数则没有被广泛实现。 正则表达式语法的某些细节在每个实现中很可能各不相同。
SQL 标准的操作符和函数使用 XQuery 正则表达式, 它与上文描述的 ARE 语法相当接近。 现有的基于 POSIX 的正则表达式特性与 XQuery 正则表达式之间值得注意的差异包括:
不支持 XQuery
的字符类减法。
这个特性的一个例子是使用下面的写法只匹配英语辅音字母:
[a-z-[aeiou]]。
不支持 XQuery
字符类简写
\c、
\C、
\i
和
\I。
不支持使用
\p{UnicodeProperty}
或其反向
\P{UnicodeProperty}
的 XQuery
字符类元素。
POSIX 根据当前的区域设置解释诸如
\w
之类的字符类
(参见
Table 9.21;
你可以通过向操作符或函数附加一个
COLLATE
子句来控制它)。
XQuery 通过参照 Unicode
字符属性来规定这些类,
因此只有在使用遵循 Unicode
规则的区域设置时才能获得等价的行为。
SQL 标准
(并非 XQuery 本身)
试图比 POSIX
兼容更多种类的
“换行”。
上面描述的换行敏感匹配选项只把 ASCII
的 NL
(\n)
视为换行,
但 SQL
会让我们把 CR
(\r)、
CRLF
(\r\n,
一种 Windows 风格的换行)
以及某些只在 Unicode
中存在的字符
(例如行分隔符 LINE SEPARATOR
(U+2028))
也当作换行。
特别地,
按照 SQL,
. 和
\s
应当把
\r\n
算作一个字符而非两个。
在
Table 9.20
中描述的字符项转义中,
XQuery 只支持
\n、
\r
和
\t。
XQuery 不支持在方括号表达式中为字符类使用
[:
语法。
name:]
XQuery 没有前向查找或后向查找约束, 也没有 Table 9.22 中描述的任何约束转义。
Section 9.7.3.4 中描述的元语法形式在 XQuery 中不存在。
XQuery
定义的正则表达式标志字母与 POSIX
的选项字母
(Table 9.24)
相关但并不相同。
虽然
i 和
q
选项的行为相同,
但其他选项并非如此:
XQuery 的
s
(允许点匹配换行)
和 m
(允许
^ 和
$
在换行处匹配)
标志提供的访问,
与 POSIX 的
n、
p
和 w
标志的行为相同,
但它们与 POSIX 的
s 和
m
标志的行为
不匹配。
特别要注意,
点匹配换行是 POSIX
中的默认行为,
但在 XQuery
中不是。
XQuery 的
x
(忽略模式中的空白)
标志与 POSIX
的展开模式标志有显著的不同。
POSIX 的
x
标志还允许
#
开始模式中的一条注释,
并且 POSIX
不会忽略反斜杠之后的空白字符。