# 9.7.模式匹配
PostgreSQL提供了三种不同的模式匹配方法:传统SQL喜欢
接线员,最近的类似
运算符(在SQL:1999中添加)和POSIX样式的正则表达式。除了基本的“这个字符串匹配这个模式吗?”运算符、函数可用于提取或替换匹配的子字符串,以及在匹配位置拆分字符串。
# 提示
如果有模式匹配的需求超出了这个范围,请考虑在Perl或Tcl中编写用户定义函数。
# 小心
虽然大多数正则表达式搜索可以非常快速地执行,但正则表达式可以被设计成需要任意数量的时间和内存来处理。小心接受来自敌对来源的正则表达式搜索模式。如果必须这样做,建议强制语句超时。
使用类似
模式也有同样的安全隐患,因为类似
提供许多与POSIX风格正则表达式相同的功能。
喜欢
搜索比其他两个选项简单得多,在使用可能有敌意的模式源时更安全。
这三种类型的模式匹配运算符都不支持非确定性排序。如果需要,请对表达式应用不同的排序规则以绕过此限制。
# 9.7.1.喜欢
string LIKE pattern [ESCAPE escape-character]
string NOT LIKE pattern [ESCAPE escape-character]
这个喜欢
如果*一串
匹配提供的图案
*(正如所料不像
如果喜欢
返回true,反之亦然。一个等价的表达式是不是(*
一串*就像*
图案*)
.)
如果*图案
不包含百分号或下划线,则模式仅表示字符串本身;那样的话喜欢
就像equals操作符一样。下划线(_
)在图案
*代表(匹配)任何单个字符;百分号(%
)匹配零个或多个字符的任意序列。
例如:
'abc' LIKE 'abc' true
'abc' LIKE 'a%' true
'abc' LIKE '_b_' true
'abc' LIKE 'c' false
喜欢
模式匹配始终覆盖整个字符串。因此,如果希望匹配字符串中任意位置的序列,则模式必须以百分号开始和结束。
要匹配文字下划线或百分号而不匹配其他字符,请在*图案
*必须以转义字符开头。默认转义字符是反斜杠,但可以使用逃跑
条款要匹配转义字符本身,请编写两个转义字符。
# 笔记
如果你有标准_一致的_串如果禁用此选项,您在文字字符串常量中写入的任何反斜杠都需要加倍。看见第4.1.2.1节了解更多信息。
也可以通过书写选择无转义字符逃走“
。这有效地禁用了转义机制,从而无法关闭模式中下划线和百分号的特殊含义。
根据SQL标准,省略逃跑
意味着没有转义字符(而不是默认为反斜杠),长度为零逃跑
价值是不允许的。因此,PostgreSQL在这方面的行为有点不规范。
关键词我喜欢
可以用来代替喜欢
根据活动区域设置使匹配不区分大小写。这不在SQL标准中,而是PostgreSQL扩展。
接线员~~
相当于喜欢
和~~*
对应于我喜欢
.还有!~~
和!~~*
代表不像
和我不喜欢
分别地所有这些操作符都是特定于PostgreSQL的。您可以在中看到这些运算符名称解释
输出和类似的地方,因为解析器实际上是翻译的喜欢
等等,这些操作员。
短语喜欢
, 我喜欢
, 不像
和我不喜欢
在PostgreSQL语法中通常被视为运算符;例如,它们可以用于*表示
* 操作人员
任何(子查询
)构造,尽管逃跑
条款不能包含在那里。在某些不清楚的情况下,可能需要使用基础运算符名称。
另请参见前缀运算符^@
以及相应的从…开始
函数,在需要简单匹配字符串开头的情况下非常有用。
# 9.7.2. 类似
正则表达式
string SIMILAR TO pattern [ESCAPE escape-character]
string NOT SIMILAR TO pattern [ESCAPE escape-character]
这个类似
运算符根据其模式是否匹配给定字符串返回true或false。类似于喜欢
,但它使用SQL标准的正则表达式定义来解释模式。SQL正则表达式是两者之间的奇怪交叉喜欢
符号和通用(POSIX)正则表达式符号。
喜欢喜欢
这个类似
运算符只有在其模式与整个字符串匹配时才成功;这与常见的正则表达式行为不同,在正则表达式行为中,模式可以匹配字符串的任何部分。也像喜欢
, 类似
使用_
和%
作为通配符,分别表示任何单个字符和任何字符串(它们与.
和.*
在POSIX正则表达式中)。
除了这些从喜欢
, 类似
支持从POSIX正则表达式借用的模式匹配元字符:
|
表示交替(两个备选方案中的任意一个)。*
表示前一项重复零次或多次。+
表示前一项重复一次或多次。?
表示前一项的重复次数为零或一次。{
m
}
表示前一项的重复*m
*时报。{
m
,}
表示上一项的重复*m
*或者更多次。{
m
,
n
}
表示至少重复上一项*m
不超过n
*时报。圆括号
()
可用于将项分组为单个逻辑项。括号表达式
[...]
指定字符类,就像在POSIX正则表达式中一样。请注意(
.
)不是一个元字符类似
.就像
喜欢
,反斜杠禁用这些元字符的特殊含义。可以使用指定不同的转义字符逃跑
,或者可以通过写入来禁用转义功能逃走“
.根据SQL标准,省略
逃跑
意味着没有转义字符(而不是默认为反斜杠),长度为零逃跑
价值是不允许的。因此,PostgreSQL在这方面的行为有点不规范。另一个非标准扩展是,在转义字符后面加一个字母或数字可以访问为POSIX正则表达式定义的转义序列;看见表9.20, 表9.21和表9.22在下面
例如:
'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
这个子串
具有三个参数的函数提供了匹配SQL正则表达式模式的子字符串的提取。该函数可以根据标准SQL语法编写:
substring(string similar pattern escape escape-character)
或者使用现在已经过时的SQL:1999语法:
substring(string from pattern for escape-character)
或者作为一个简单的三参数函数:
substring(string, pattern, escape-character)
就像类似
,指定的模式必须与整个数据字符串匹配,否则函数将失败并返回null。要指示匹配数据子字符串感兴趣的模式部分,该模式应包含两个转义字符,后跟一个双引号("
).匹配成功后,将返回与这些分隔符之间的图案部分匹配的文本。
转义双引号分隔符实际上是分开的子串
的模式转换为三个独立的正则表达式;例如,竖条(|
)在这三个部分中,任何一个都只影响该部分。此外,当有多少数据字符串与哪个模式匹配存在歧义时,这些正则表达式中的第一个和第三个被定义为匹配尽可能少的文本量,而不是最大的文本量。(用POSIX的说法,第一个和第三个正则表达式必须是非贪婪的。)
作为SQL标准的扩展,PostgreSQL只允许有一个转义双引号分隔符,在这种情况下,第三个正则表达式被视为空;或者没有分隔符,在这种情况下,第一个和第三个正则表达式被视为空。
一些例子#"
分隔返回字符串:
substring('foobar' similar '%#"o_b#"%' escape '#') oob
substring('foobar' similar '#"o_b#"%' escape '#') NULL
# 9.7.3.POSIX正则表达式
表9.16列出使用POSIX正则表达式进行模式匹配的可用运算符。
表9.16.正则表达式匹配运算符
操作人员 描述 例子 |
---|
文本 ~ 文本 → 布尔值 字符串匹配正则表达式,区分大小写 “托马斯”~“妈妈” → t |
文本 ~* 文本 → 布尔值 字符串匹配正则表达式,不区分大小写 “托马斯”~*'T.*ma' → t |
文本 !~ 文本 → 布尔值 字符串与正则表达式不匹配,区分大小写 “托马斯”!~”t、 *max' → t |
文本 !~* 文本 → 布尔值 字符串与正则表达式不匹配,不区分大小写 “托马斯”!~*'T.*ma' → f |
POSIX正则表达式为模式匹配提供了比喜欢
和类似
接线员。许多Unix工具,例如白鹭
, 塞德
或啊
使用与本文所述类似的模式匹配语言。
正则表达式是一个字符序列,是一组字符串(A)的缩写定义正则集).如果字符串是正则表达式所描述的正则集的成员,则称其与正则表达式匹配。就像喜欢
,模式字符与字符串完全匹配,除非它们是正则表达式语言中的特殊字符,但正则表达式使用的特殊字符与喜欢
做不像喜欢
在模式中,正则表达式可以匹配字符串中的任何位置,除非正则表达式显式锚定到字符串的开头或结尾。
例如:
'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模式语言将在下面进行更详细的描述。
这个子串
具有两个参数的函数,子串(*
一串*来自*
图案*)
,提供与POSIX正则表达式模式匹配的子字符串的提取。如果不匹配,则返回null,否则返回与模式匹配的文本的第一部分。但是,如果模式包含任何括号,则返回与第一个带括号的子表达式(左括号排在第一位的子表达式)匹配的文本部分。如果希望在表达式中使用括号而不触发此异常,可以在整个表达式周围放置括号。如果需要在模式中提取子表达式之前使用括号,请参阅下面描述的非捕获括号。
例如:
substring('foobar' from 'o.b') oob
substring('foobar' from 'o(.)b') o
这个regexp_替换
函数为匹配POSIX正则表达式模式的子字符串提供新文本的替换。它有语法regexp_替换
(来源
, 图案
, 替换
[, 旗帜
]).这个*来源
如果与字符串不匹配,则返回的字符串将保持不变图案
.如果有匹配项,则来源
字符串与替换
字符串替换了匹配的子字符串。这个替换
字符串可以包含\
n
哪里n
是1到9,表示源子字符串与n
'应该插入模式的括号子表达式,并且它可以包含\&
指示应插入与整个模式匹配的子字符串。写\\
如果需要在替换文本中加上反斜杠。这个旗帜
*参数是一个可选的文本字符串,包含零个或多个单字母标志,用于更改函数的行为。旗帜我
指定不区分大小写的匹配,同时标记g
指定替换每个匹配的子字符串,而不是仅替换第一个子字符串。支持的标志(尽管不是g
)如中所述表9.24.
例如:
regexp_replace('foobarbaz', 'b..', 'X')
fooXbaz
regexp_replace('foobarbaz', 'b..', 'X', 'g')
fooXX
regexp_replace('foobarbaz', 'b(..)', 'X\1Y', 'g')
fooXarYXazY
这个正则表达式匹配
函数返回从POSIX正则表达式模式与字符串的第一次匹配中获取的子字符串的文本数组。它有语法正则表达式匹配
(一串
, 图案
[, 旗帜
]).如果没有匹配项,则结果为无效的
.如果找到匹配项*图案
不包含带括号的子表达式,则结果是一个包含与整个模式匹配的子字符串的单元素文本数组。如果找到匹配项图案
包含带括号的子表达式,则结果是一个文本数组n
'th元素是与n
'带括号的子表达式图案
(不包括“非捕获”括号;详见下文)。这个旗帜
*参数是一个可选的文本字符串,包含零个或多个单字母标志,用于更改函数的行为。中介绍了支持的标志表9.24.
例如:
SELECT regexp_match('foobarbequebaz', 'bar.*que');
regexp_match
### Tip
In most cases `regexp_matches()` should be used with the `g` flag, since if you only want the first match, it's easier and more efficient to use `regexp_match()`. However, `regexp_match()` only exists in PostgreSQL version 10 and up. When working in older versions, a common trick is to place a `regexp_matches()` call in a sub-select, for example:
从选项卡中选择col1(选择regexp_matches(col2),(bar)(beque));
This produces a text array if there's a match, or `NULL` if not, the same as `regexp_match()` would do. Without the sub-select, this query would produce no output at all for table rows without a match, which is typically not the desired behavior.
The `regexp_split_to_table` function splits a string using a POSIX regular expression pattern as a delimiter. It has the syntax `regexp_split_to_table`(*`string`*, *`pattern`* [, *`flags`* ]). If there is no match to the *`pattern`*, the function returns the *`string`*. If there is at least one match, for each match it returns the text from the end of the last match (or the beginning of the string) to the beginning of the match. When there are no more matches, it returns the text from the end of the last match to the end of the string. The *`flags`* parameter is an optional text string containing zero or more single-letter flags that change the function's behavior. `regexp_split_to_table` supports the flags described in [Table 9.24](functions-matching.html#POSIX-EMBEDDED-OPTIONS-TABLE).
The `regexp_split_to_array` function behaves the same as `regexp_split_to_table`, except that `regexp_split_to_array` returns its result as an array of `text`. It has the syntax `regexp_split_to_array`(*`string`*, *`pattern`* [, *`flags`* ]). The parameters are the same as for `regexp_split_to_table`.
Some examples:
从regexp_split_to_table中选择foo('快速棕色狐狸跳过懒狗','\s+')作为foo;福
# 9.7.3.1.正则表达式详细信息
PostgreSQL的正则表达式是使用Henry Spencer编写的软件包实现的。下面对正则表达式的大部分描述都是从他的手册中逐字复制的。
POSIX 1003.2中定义的正则表达式(REs)有两种形式:延长REs或EREs(大致指白鹭
),及基本的REs或BREs(大致为预计起飞时间
).PostgreSQL支持这两种形式,还实现了POSIX标准中没有的一些扩展,但由于它们在Perl和Tcl等编程语言中的可用性,已经被广泛使用。使用这些非POSIX扩展的REs称为先进的本文档中的REs或AREs。战神几乎完全是ERE的超集,但BRE在符号上有几个不兼容之处(而且要有限得多)。我们首先描述ARE和ERE形式,指出仅适用于ARE的特征,然后描述BRE的不同之处。
# 笔记
PostgreSQL最初总是假定正则表达式遵循ARE规则。然而,更有限的ERE或BRE规则可以通过预先设置嵌入期权如中所述,切换到重新模式第9.7.3.4节。这有助于与完全符合POSIX 1003.2规则的应用程序兼容。
正则表达式定义为一个或多个树枝,由|
.它匹配任何与其中一个分支匹配的东西。
分支为零或更多量化原子或约束条件,连接。它与第一个匹配,然后与第二个匹配,等等;空分支与空字符串匹配。
一个被量化的原子是一个原子原子可能后面跟着一个数量词.如果没有量词,它与原子匹配。有了量词,它可以匹配原子的一些匹配项。一原子可以是中显示的任何可能性表9.17.可能的量词及其含义如所示表9.18.
A.限制匹配空字符串,但仅在满足特定条件时匹配。可以在原子可以被使用的地方使用约束,除非它后面不能跟一个量词。中显示了简单的约束表9.19; 后面将描述更多的约束。
表9.17.正则表达式原子
原子 | 描述 |
---|---|
( 重新 ) | (在哪里*重新 是任何正则表达式)匹配的重新 *,这场比赛可能会被报道 |
(?: 重新 ) | 如上所述,但该匹配不以报告(一组“非捕获”的括号)著称(仅限战神) |
. | 匹配任何单个字符 |
[ 查斯 ] | A.括号表达式,匹配任何一个*查斯 *(见第9.7.3.2节(如需了解更多详细信息) |
\ k |(在哪里*k *是非字母数字字符)匹配作为普通字符的字符,例如。,\\ 匹配反斜杠字符 | |
\ c |在哪里*c 是字母数字(可能后跟其他字符)是逃跑看见第9.7.3.3节(仅限战神;在厄里斯和布雷斯,这两种情况是匹配的c *) | |
{ | 后跟数字以外的字符时,与左大括号字符匹配{ ; 当后跟一个数字时,它是一个数字的开始*跳跃 *(见下文) |
十、 | 哪里*十、 *是一个没有其他意义的单一字符,与该字符匹配 |
RE不能以反斜杠结尾(\
).
# 笔记
如果你有标准_一致的_串如果禁用此选项,您在文字字符串常量中写入的任何反斜杠都需要加倍。看见第4.1.2.1节了解更多信息。
表9.18.正则表达式量词
数量词 | 比赛 |
---|---|
* | 原子的0个或多个匹配的序列 |
+ | 原子的一个或多个匹配的序列 |
? | 原子的0或1匹配序列 |
{ m } | 一系列*m *原子的匹配 |
{ m ,} | 一连串的*m *或者更多的原子匹配 |
{ m , n } | 一连串的*m 通过n (含)原子匹配;m 不能超过n * |
*? | 非贪婪版本的* |
+? | 非贪婪版本的+ |
?? | 非贪婪版本的? |
{ m }? | 非贪婪版本的{ m } |
{ m ,}? | 非贪婪版本的{ m ,} |
{ m , n }? | 非贪婪版本的{ m , n } |
使用{
...
}
被称为界限.数字*m
和n
*在一个范围内是允许值为0到255(含0到255)的无符号十进制整数。
不贪婪量词(仅在战神中可用)与其对应的正常值匹配相同的可能性(贪婪的)对等,但更喜欢最小数量的匹配,而不是最大数量的匹配。看见第9.7.3.5节更多细节。
# 笔记
一个量词不能紧跟另一个量词,例如:。,**
无效。量词不能以表达式或子表达式开头或后跟^
或|
.
表9.19.正则表达式约束
限制 | 描述 |
---|---|
^ | 匹配字符串的开头 |
$ | 字符串末尾的匹配项 |
(?= 重新 ) | 积极展望在子字符串匹配的任何点匹配*重新 *开始(仅限战神) |
(?! 重新 ) | 消极前瞻在没有子字符串匹配的任何点匹配*重新 *开始(仅限战神) |
(?<= 重新 ) | 正面回顾在子字符串匹配的任何点匹配*重新 *完(仅限战神) |
(?<! 重新 ) | 消极落后在没有子字符串匹配的任何点匹配*重新 *完(仅限战神) |
前向和后向约束不能包含反向引用(见第9.7.3.3节),其中的所有括号都被视为非捕获。
# 9.7.3.2.括号表达式
A.括号表达式是包含在中的字符列表[]
。它通常匹配列表中的任何单个字符(但请参见下文)。如果列表以^
,它匹配任何单个字符不从名单的其他部分。如果列表中的两个字符用-
,这是排序序列中这两个(包括)字符之间的完整范围的缩写,例如。,[0-9]
在ASCII中匹配任何十进制数字。两个范围共享一个端点是非法的,例如。,a-c-e
.范围非常依赖于排序顺序,因此可移植程序应避免依赖它们。
包含文字]
在列表中,将其作为第一个字符(在^
,如果使用)。包含文字-
,使其成为范围的第一个或最后一个字符,或第二个端点。用字面意思-
作为范围的第一个端点,将其括在[.
和.]
使其成为一个排序元素(见下文)。除这些字符外,有些组合使用[
(见下一段)和转义(仅限战神),所有其他特殊字符在括号表达式中失去了特殊意义。特别地,\
在遵循ERE或BRE规则时并不特别,尽管它在战神中是特别的(比如引入逃跑)。
在括号表达式中,括在括号中的排序元素(字符、按单个字符排序的多字符序列,或任意字符的排序序列名称)[.
和.]
表示该排序元素的字符序列。序列被视为括号表达式列表中的单个元素。这允许包含多字符排序元素的括号表达式匹配多个字符,例如,如果排序序列包含中国
排序元素,然后是[ch.]*c
匹配的前五个字符CHCC
.
# 笔记
PostgreSQL目前不支持多字符排序元素。该信息描述了未来可能的行为。
在括号表达式中,包含在括号中的排序元素[=
和=]
是一个等价类,表示与该排序元素等价的所有排序元素的字符序列,包括其本身。(如果没有其他等效的排序元素,则处理方式与封闭分隔符相同。)[.
和.]
)例如,如果o
和^
是等价类的成员吗[=o=]
, [[=^=]]
和[o^]
都是同义词。等价类不能是范围的端点。
在括号表达式中,括在括号中的字符类的名称[:
和:]
表示属于该类的所有字符的列表。字符类不能用作范围的终结点。POSIX标准定义了以下字符类名称:阿尔纳姆
(字母和数字),阿尔法
(信件),空白的
(空格和制表符),cntrl
(控制字符),数字
(数字),图表
(可打印字符,空格除外),降低
(小写字母),打印
(可打印字符,包括空格),点刺
(标点符号),空间
(任何空白),上面的
(大写字母),以及xdigit
(十六进制数字)。对于7位ASCII集中的字符,这些标准字符类的行为在不同平台上通常是一致的。给定的非ASCII字符是否被视为属于这些类别之一取决于校勘用于正则表达式函数或运算符(请参见第24.2节),或默认情况下在数据库的LC_CTYPE
区域设置(请参见第24.1节)。非ASCII字符的分类可能因平台而异,即使在名称类似的地区也是如此。(但是C
locale从不认为任何非ASCII字符属于这些类别。)除了这些标准字符类,PostgreSQL还定义了单词
字符类,与阿尔纳姆
加上下划线(_
)性格,以及ascii码
字符类,它正好包含7位ASCII集。
括号表达式有两种特殊情况:括号表达式[[:<:]]
和[[:>:]]
是约束,分别匹配单词开头和结尾的空字符串。一个单词被定义为一系列既不在单词前面也不在单词后面的单词字符。单词字符是属于单词的任何字符单词
字符类,即任何字母、数字或下划线。这是一个扩展,与POSIX 1003.2兼容,但不是POSIX 1003.2指定的扩展,在打算移植到其他系统的软件中应谨慎使用。下面描述的约束转义通常更可取;它们不再标准,但更容易打字。
# 9.7.3.3.正则表达式逃逸
逃脱是以…开头的特殊序列吗\
后跟字母数字字符。转义有几种类型:字符输入、类速记、约束转义和反向引用。A.\
后跟字母数字字符但不构成有效转义在战神中是非法的。在ERE中,没有转义:在括号表达式之外,是\
后跟字母数字字符仅代表普通字符,在括号表达式中,\
是一个普通的角色。(后者是ERE和ARE之间的一个实际不兼容。)
字符输入转义exist使在REs中指定非打印字符和其他不方便的字符更容易。它们显示在表9.20.
课堂速记逃课为某些常用字符类提供简写。它们显示在表9.21.
A.约束逃逸是一个约束,在满足特定条件时匹配空字符串,写为转义。它们显示在表9.22.
A.反向引用 (\
n
)匹配由数字指定的上一个带括号的子表达式匹配的同一字符串*n
*(见表9.23).例如,([bc])\1
比赛bb
或复写的副本
但不是公元前
或cb
.子表达式必须完全位于RE中的反向引用之前。子表达式按其前括号的顺序编号。非捕获括号不定义子表达式。back引用只考虑被引用子表达式匹配的字符串,而不考虑其中包含的任何约束。例如(^\d)\1
将匹配22
.
表9.20.正则表达式字符项转义
逃跑 | 描述 |
---|---|
\a | 警惕(bell)字符,如在C中 |
\b | 退格,如C |
\B | 反斜杠的同义词(\ )帮助减少反斜杠加倍的需要 |
\c 十、 | (在哪里*十、 是任何字符)其低阶5位与十、 *,其其他位均为零 |
\e | 排序序列名称为的字符电子稳定控制系统 ,否则,就是八进制值的字符033 |
\f | 表单提要,如C中的 |
\n | 换行符,如C |
\r | 回车,如在C中 |
\t | 水平制表符,如C |
\u wxyz | (在哪里*wxyz 正好是四个十六进制数字)十六进制值为0x wxyz * |
\U stuvwxyz | (在哪里*stuvwxyz 正好是八个十六进制数字)十六进制值为0x stuvwxyz * |
\五 | 垂直制表符,如C |
\x 啊 | (在哪里*啊 是任何十六进制数字序列)其十六进制值为0x 啊 *(无论使用多少个十六进制数字,都是一个字符) |
\0 | 其值为0 (空字节) |
\ xy |(在哪里*xy 正好是两个八进制数字,不是反向引用*)八进制值为的字符0 xy | |
\ xyz |(在哪里*xyz 正好是三个八进制数字,不是反向引用*)八进制值为的字符0 xyz |
十六进制数字是0
-9
, A.
-f
和A.
-F
.八进制数字是0
-7.
.
指定ASCII范围(0–127)之外的值的数字字符条目转义的含义取决于数据库编码。例如,当编码为UTF-8时,转义值相当于Unicode代码点\u1234
意思是角色U+1234
.对于其他多字节编码,字符条目转义通常只指定字符字节值的串联。如果转义值与数据库编码中的任何合法字符都不对应,则不会引发错误,但它永远不会匹配任何数据。
字符输入转义符始终被视为普通字符。例如\135
是]
用ASCII码,但是\135
不终止括号表达式。
表9.21.正则表达式类速记转义
逃跑 | 描述 |
---|---|
\d | 匹配任何数字,比如[:数字:] |
\s | 匹配任何空白字符,如[:空格:] |
\w | 匹配任何单词字符,比如[:单词:] |
\D | 匹配任何非数字,比如[^[:数字:] |
\S | 匹配任何非空白字符,如[^[:空格:] |
\W | 匹配任何非单词字符,如[^[:单词:] |
类速记转义也可以在括号表达式中使用,尽管上面显示的定义在该上下文中在语法上不太有效。例如[a-c\d]
相当于[a-c[:数字:]
.
表9.22.正则表达式约束转义
逃跑 | 描述 |
---|---|
\A | 仅在字符串开头匹配(请参见第9.7.3.5节这和^ ) |
\m | 仅在单词开头匹配 |
\M | 仅在单词末尾匹配 |
\y | 仅在单词的开头或结尾匹配 |
\Y | 仅在不是单词开头或结尾的点匹配 |
\Z | 仅在字符串末尾匹配(请参见第9.7.3.5节这和$ ) |
一个词的定义如[[:<:]]
和[[:>:]]
在上面括号表达式中的约束转义是非法的。
表9.23.正则表达式反向引用
逃跑 | 描述 |
---|---|
\ m |(在哪里*m 是一个非零数字)是对m *'th子表达式 | |
\ mnn |(在哪里*m 是一个非零数字,并且nn 是更多的数字,以及十进制值mnn 不大于到目前为止看到的右括号数)返回到mnn *'th子表达式 |
# 笔记
八进制字符条目转义和反向引用之间存在固有的模糊性,如上文所述,这可以通过以下启发式方法解决。前导零总是表示八进制逃逸。一个非零的数字,后面不跟另一个数字,总是作为反向参考。如果一个不以零开头的多位数序列位于一个合适的子表达式之后(即,该数字在反引用的合法范围内),则将其作为反引用,否则将其作为八进制。
# 9.7.3.4.正则表达式元语法
除了上面描述的主要语法之外,还有一些特殊的形式和各种各样的语法工具。
RE可以从两个特殊的选项中的一个开始经理前缀。如果重新开始***:
,剩余的RE被视为ARE。(这在PostgreSQL中通常不起作用,因为REs被假定为are;但如果ERE或BRE模式已由*旗帜
*参数设置为正则表达式函数。)如果重新开始***=
,RE的其余部分被视为文字字符串,所有字符都被视为普通字符。
ARE可以从嵌入选项:序列(?
xyz
)
(在哪里*xyz
是一个或多个字母字符)指定影响RE其余部分的选项。这些选项会覆盖任何以前确定的选项,尤其是,它们可以覆盖正则表达式运算符或旗帜
正则表达式函数的参数。可用选项字母如所示表9.24。请注意,这些选项字母在旗帜
*正则表达式函数的参数。
表9.24.是嵌入的选项字母
选项 | 描述 |
---|---|
b | RE的其余部分是BRE |
c | 区分大小写的匹配(覆盖运算符类型) |
e | RE的其余部分是一个ERE |
我 | 不区分大小写的匹配(请参见第9.7.3.5节)(覆盖运算符类型) |
m | 历史同义词n |
n | 换行符敏感匹配(参见第9.7.3.5节) |
p | 部分换行符敏感匹配(参见第9.7.3.5节) |
q | RE的其余部分是一个文字(“引号”)字符串,都是普通字符 |
s | 非换行符敏感匹配(默认) |
t | 紧凑语法(默认;见下文) |
w | 反向部分换行敏感(“怪异”)匹配(参见第9.7.3.5节) |
十、 | 扩展语法(见下文) |
嵌入选项在)
终止序列。它们只能出现在ARE的开头(在***:
董事(如有)。
除了平常(牢固的)重新语法,其中所有字符都是重要的,有一个扩大语法,可通过指定嵌入的十、
选项在扩展语法中,RE中的空白字符被忽略,字符之间的所有字符也是如此#
以及下面的新行(或RE的结尾)。这允许对一个复杂的问题进行分段和评论。这一基本规则有三个例外:
空白字符或
#
前面是\
保留空白或
#
在括号内保留表达式空格和注释不能出现在多字符符号中,例如
(?:
为此,空白字符包括空格、制表符、换行符和属于*
空间
*角色课。最后,在ARE中,外括号表达式
(?#
ttt
)
(在哪里*ttt
*是否有任何文本不包含)
)这是一个评论,完全被忽略了。同样,这在多字符符号的字符之间是不允许的,比如(?:
。这些评论与其说是有用的工具,不如说是历史产物,而且它们的使用受到了反对;改用扩展语法。
没有一个如果首字母为***=
director已指定将用户的输入视为文字字符串,而不是RE。
# 9.7.3.5.正则表达式匹配规则
如果RE可以匹配给定字符串的多个子字符串,则RE将匹配字符串中最早开始的子字符串。如果RE可以从该点开始匹配多个子串,则根据RE是否匹配,将进行最长或最短的匹配贪婪的或非贪婪.
RE是否贪婪取决于以下规则:
大多数原子和所有约束都没有贪婪属性(因为它们无论如何都无法匹配可变数量的文本)。
在RE周围添加括号并不会改变它的贪婪程度。
带有固定重复量词的量化原子(
{
m
}
或{
m
}?
)和原子本身一样贪婪(可能没有)。与其他正常量词(包括
{
m
,
n
}
具有*m
相当于n
*)贪婪(喜欢最长的比赛)。带有非贪婪量词的量化原子(包括
{
m
,
n
}?
具有*m
相当于n
*)不贪婪(更喜欢最短匹配)。一个分支——也就是说,一个没有顶层的RE
|
运算符-与其中第一个具有贪婪属性的量化原子具有相同的贪婪性。由两个或多个分支通过
|
接线员总是很贪婪。上述规则不仅将贪婪属性与单个量化原子相关联,还将贪婪属性与包含量化原子的分支和整个REs相关联。这意味着匹配是以这样一种方式进行的,即分支或整个RE匹配最长或最短的子字符串作为一个整体.一旦确定了整个匹配的长度,匹配任何特定子表达式的部分将基于该子表达式的贪婪属性来确定,子表达式将优先于从后面开始的子表达式。
这意味着什么的一个例子:
SELECT SUBSTRING('XY1234Z', 'Y*([0-9]{1,3})');
Result: 123
SELECT SUBSTRING('XY1234Z', 'Y*?([0-9]{1,3})');
Result: 1
在第一种情况下,RE 作为一个整体是贪婪的,因为是*
是贪婪的。它可以匹配从是
,并且它匹配从那里开始的最长可能字符串,即Y123
.输出是括号内的部分,或者123
.在第二种情况下,RE 作为一个整体是非贪婪的,因为你*?
是非贪婪的。它可以匹配从是
,并且它匹配从那里开始的最短可能字符串,即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*
匹配的三个中间字符美国广播公司
;(周|凌晨)(夜|骑士)
匹配所有十个字符平日之夜
;什么时候(.*).*
匹配美国广播公司
括号内的子表达式匹配所有三个字符;什么时候(一种*)*
匹配公元前
整个 RE 和带括号的子表达式都匹配一个空字符串。
如果指定了与大小写无关的匹配,则效果就像所有大小写区别都从字母表中消失一样。当存在于多种情况下的字母作为普通字符出现在括号表达式之外时,它会有效地转换为包含两种情况的括号表达式,例如,x
变成[xX]
.当它出现在括号表达式中时,它的所有大小写对应项都将添加到括号表达式中,例如,[x]
变成[xX]
和[^x]
变成[^xX]
.
如果指定了换行符敏感匹配,.
和括号表达式使用^
将永远不会匹配换行符(因此,除非RE显式包含换行符,否则匹配不会跨行),并且^
和$
将分别匹配换行符之后和之前的空字符串,此外还将分别匹配字符串的开头和结尾。但这些都是逃避\A
和\Z
继续匹配字符串的开头或结尾只有.此外,角色类速记\D
和\W
无论此模式如何,都将匹配换行符。(在PostgreSQL 14之前,当处于新行敏感模式时,它们不匹配新行。写入[^[:数字:]
或[^[:单词:]
以获得旧的行为。)
如果指定了部分换行符敏感匹配,则会影响.
括号表达式与新行敏感匹配一样,但不是^
和$
.
如果指定了反向部分换行符敏感匹配,则会影响^
和$
与新行敏感匹配一样,但不是.
和括号表达式。这不是很有用,但是为了对称而提供的。
# 9.7.3.6.限制和兼容性
在这个实现中,对REs的长度没有特别的限制。然而,打算高度可移植的程序不应使用长度超过256字节的REs,因为符合POSIX的实现可能会拒绝接受此类REs。
战神唯一与POSIX EREs不兼容的特征是\
在括号表达式中不会失去其特殊意义。所有其他功能使用的语法在POSIX EREs中是非法的,或具有未定义或未指定的效果;这个***
对于BRE和ERE,控制器的语法同样不在POSIX语法的范围内。
许多ARE扩展都是从Perl中借来的,但有些已经被修改以清理它们,还有一些Perl扩展不存在。值得注意的不兼容性包括\b
, \B
,缺少对尾随换行符的特殊处理,在受换行符敏感匹配影响的内容中添加了补足括号表达式,在前向/后向约束中对括号和后向引用的限制,以及最长/最短匹配(而不是第一次匹配)匹配语义。
# 9.7.3.7.基本正则表达式
BRE在几个方面与ERE不同。在布雷斯,|
, +
和?
都是普通字符,其功能没有等价物。边界的分隔符是\{
和\}
具有{
和}
它们本身就是普通的人物。嵌套子表达式的括号是\(
和\)
具有(
和)
它们本身就是普通的人物。^
是普通字符,但RE开头或括号子表达式开头除外,$
是一个普通字符,但在RE结尾或括号子表达式结尾处除外,以及*
是一个普通字符,如果它出现在RE的开头或带括号的子表达式的开头(在可能的前导之后)^
)。最后,可提供一位数的背面参考,以及\<
和\>
是的同义词[[:<:]]
和[[:>:]]
分别地在布雷斯没有其他逃生途径。
# 9.7.3.8.与XQuery的区别(比如_REGEX
)
自SQL:2008以来,SQL标准包括比如_REGEX
根据XQuery正则表达式标准执行模式匹配的运算符。PostgreSQL尚未实现此运算符,但使用regexp_match()
函数,因为XQuery正则表达式与上述are语法非常接近。
现有的基于POSIX的正则表达式功能与XQuery正则表达式之间的显著区别包括:
不支持XQuery字符类减法。此功能的一个示例是使用以下方法仅匹配英语辅音:
[a-z-[aeiou]]
.XQuery字符类速记
\c
,\C
,\我
和\我
不支持。使用
\p{UnicodeProperty}
还是反过来\P{UnicodeProperty}
不支持。POSIX解释字符类,例如
\w
(见表9.21)根据当前的区域设置(您可以通过附加整理
子句(对运算符或函数)。XQuery通过引用Unicode字符属性指定这些类,因此只有在遵循Unicode规则的区域设置下才能获得等效的行为。与POSIX相比,SQL标准(而不是XQuery本身)试图适应更多的“新行”变体。上文所述的换行敏感匹配选项仅考虑ASCII NL(
\n
)作为一个新词,SQL会让我们(\r
),CRLF(\r\n
)(Windows样式的换行符),以及一些仅限Unicode的字符,例如换行符(U+2028)。尤其是.
和\s
应该算数\r\n
根据SQL,一个字符不是两个字符。中所述的字符项转义表9.20,XQuery仅支持
\n
,\r
和\t
.XQuery不支持
[:*
名称*:]
括号表达式中字符类的语法。XQuery没有前向或后向约束,也没有中描述的任何约束转义表9.22.
中描述的元语法形式第9.7.3.4节在XQuery中不存在。
XQuery定义的正则表达式标志字母与POSIX的选项字母相关,但不同(表9.24).而
我
和q
选项的行为相同,其他选项则不同:XQuery的
s
(允许点匹配换行符)和m
(允许^
和$
在换行符处匹配)标志提供与POSIX相同的行为的访问n
,p
和w
旗子,但他们有不匹配POSIX的行为s
和m
旗帜。请特别注意,点匹配换行符是POSIX中的默认行为,而不是XQuery。XQuery的
十、
(忽略模式中的空白)标志明显不同于POSIX的扩展模式标志。POSIX's十、
国旗也允许#
在模式中开始注释,POSIX不会忽略反斜杠后面的空白字符。