2025年9月25日: PostgreSQL 18 发布!
支持的版本: 当前 (18) / 17 / 16 / 15 / 14 / 13
开发版本: devel
不支持的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1

9.7. 模式匹配 #

PostgreSQL 提供了三种独立的模式匹配方法:传统的SQL LIKE 操作符,较新的 SIMILAR TO 操作符(在 SQL:1999 中添加),以及POSIX-style 正则表达式。除了基本的“这个字符串是否匹配这个模式?”的操作符之外,还提供了用于提取或替换匹配的子字符串以及在匹配位置拆分字符串的函数。

提示

如果你的模式匹配需求超出了这些功能,可以考虑用 Perl 或 Tcl 编写用户自定义函数。

注意

虽然大多数正则表达式搜索可以非常快速地执行,但正则表达式可能被构造得需要任意数量的时间和内存来处理。在接受来自敌对来源的正则表达式搜索模式时要格外小心。如果必须这样做,建议设置语句超时。

使用 SIMILAR TO 模式的搜索也存在同样的安全性风险,因为 SIMILAR TO 提供了与POSIX-style 正则表达式相同的许多功能。

作为其他两个选项来说,LIKE 搜索要简单得多,因此在使用可能来自敌对来源的模式时更安全。

SIMILAR TOPOSIX-style 正则表达式不支持非确定性排序规则。如果需要,请使用 LIKE 或将其他排序规则应用于表达式来绕过此限制。

9.7.1. LIKE #

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

string 匹配所提供的 pattern 时,LIKE 表达式返回 true。 (正如预期的那样,如果 LIKE 返回 true,则 NOT LIKE 表达式返回 false,反之亦然。等效表达式为 NOT (string LIKE pattern)。)

如果 pattern 不包含百分号或下划线,那么模式只代表字符串本身;在这种情况下 LIKE 的作用与等于操作符相同。 pattern 中的下划线(_)代表(匹配)任何单个字符;百分号(%)匹配任何零个或多个字符的序列。

一些例子

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

LIKE 模式匹配支持非确定性排序规则(请参阅 第 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 为 true,因为 .foo. 可以划分为 .f, o, o.,然后 '.f' = 'f' COLLATE ign_punct'o' 匹配 _ 通配符,并且 'o.' = 'o' COLLATE ign_punct。但是 '.foo.' LIKE '_oo' COLLATE ign_punct 为 false,因为 .foo. 不能以第一字符是任何字符且字符串的其余部分与 oo 相等的方式进行划分。(请注意,单字符通配符始终匹配正好一个字符,与排序规则无关。所以在这个例子中,_ 会匹配 .,但字符串的其余部分将与模式的其余部分不匹配。)

LIKE 模式匹配总是覆盖整个字符串。因此,如果希望匹配字符串中的某个序列,则模式必须以百分号开头和结尾。

要匹配字面上的下划线或百分号而不匹配其他字符,pattern 中的相应字符必须在其前面加上转义字符。默认的转义字符是反斜杠,但可以使用 ESCAPE 子句选择另一个。要匹配转义字符本身,请写两个转义字符。

注意

如果 standard_conforming_strings 设置为 off,那么在字面字符串常量中写入的任何反斜杠都需要加倍。有关更多信息,请参阅 第 4.1.2.1 节

也可以通过写 ESCAPE '' 来选择不使用转义字符。这实际上禁用了转义机制,从而无法关闭下划线和百分号在模式中的特殊含义。

根据 SQL 标准,省略 ESCAPE 意味着没有转义字符(而不是默认为反斜杠),并且不允许零长度的 ESCAPE 值。因此,PostgreSQL 在这方面的行为略微不符合标准。

关键字 ILIKE 可以替代 LIKE,以根据活动区域设置进行不区分大小写的匹配。(但这不支持非确定性排序规则。)这不在SQL标准中,而是 PostgreSQL 的扩展。

操作符 ~~ 等同于 LIKE,而 ~~* 对应于 ILIKE。还有 !~~!~~* 操作符,分别代表 NOT LIKENOT ILIKE。所有这些操作符都是 PostgreSQL 特有的。你可能会在 EXPLAIN 输出及类似地方看到这些操作符名称,因为解析器实际上会将 LIKE 等转换为这些操作符。

短语 LIKEILIKENOT LIKENOT ILIKEPostgreSQL 语法中通常被视为操作符;例如,它们可以用于 expression operator ANY (subquery) 结构中,尽管那里不能包含 ESCAPE 子句。在某些晦涩的情况下,可能需要使用底层操作符名称。

另请参阅开头匹配操作符 ^@ 和相应的 starts_with() 函数,在只需要匹配字符串开头的情况下非常有用。

9.7.2. SIMILAR TO 正则表达式 #

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

取决于其模式是否匹配给定字符串,SIMILAR TO 操作符返回 true 或 false。它与 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 正则表达式中一样。

请注意,句点(.)不是 SIMILAR TO 的元字符。

LIKE 一样,反斜杠会禁用这些元字符中的任何一个的特殊含义。可以使用 ESCAPE 指定不同的转义字符,或者通过编写 ESCAPE '' 来禁用转义功能。

根据 SQL 标准,省略 ESCAPE 意味着没有转义字符(而不是默认为反斜杠),并且不允许零长度的 ESCAPE 值。因此,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

带有三个参数的 substring 函数提供了一个匹配 SQL 正则表达式模式的子字符串的提取。该函数可以根据标准 SQL 语法编写

substring(string similar pattern escape escape-character)

或者使用现已废弃的 SQL:1999 语法

substring(string from pattern for escape-character)

或者作为普通的三参数函数

substring(string, pattern, escape-character)

SIMILAR TO 一样,指定的模式必须匹配整个数据字符串,否则函数将失败并返回 null。要指示模式中匹配的数据子字符串感兴趣的部分,模式应包含两个转义字符后跟一个双引号(")。匹配分隔符之间的部分文本将在匹配成功时返回。

实际上,转义双引号分隔符将 substring 的模式划分为三个独立的正则表达式;例如,任何一个部分的竖线(|)只会影响该部分。此外,这三个正则表达式中的第一个和第三个被定义为匹配尽可能少量的文本,而不是最多的文本,当存在关于数据字符串的多少匹配模式的不确定性时。(在 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. 正则表达式匹配操作符

运算符

描述

示例

text ~ textboolean

字符串匹配正则表达式,区分大小写

' thomas' ~ 't.*ma't

text ~* textboolean

字符串匹配正则表达式,不区分大小写

' thomas' ~* 'T.*ma't

text !~ textboolean

字符串不匹配正则表达式,区分大小写

' thomas' !~ 't.*max't

text !~* textboolean

字符串不匹配正则表达式,不区分大小写

' thomas' !~* 'T.*ma'f


POSIX正则表达式比 LIKESIMILAR TO 操作符提供了更强大的模式匹配方式。许多 Unix 工具,如 egrepsedawk,都使用一种与此处描述的相似的模式匹配语言。

正则表达式是字符串序列,它是字符串集合(一个 正则表达式集)的缩写定义。如果一个字符串是该正则表达式所描述的正则表达式集的一个成员,那么该字符串就被认为匹配该正则表达式。与 LIKE 一样,模式字符精确匹配字符串字符,除非它们在正则表达式语言中是特殊字符——但正则表达式使用的特殊字符与 LIKE 不同。与 LIKE 模式不同,正则表达式允许在字符串内的任何位置进行匹配,除非正则表达式明确锚定在字符串的开头或结尾。

一些例子

'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(string from pattern),提供了匹配 POSIX 正则表达式模式的子字符串的提取。如果没有匹配,则返回 null,否则返回匹配该模式的第一个文本部分。但是,如果模式包含任何括号,则返回与第一个括号子表达式(左括号最靠前那个)匹配的文本部分。如果你想在内部使用括号而不触发此异常,可以将整个表达式用括号括起来。如果你需要在子表达式提取之前在模式中使用括号,请参阅下面描述的非捕获括号。

一些例子

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

函数 regexp_count 计算 POSIX 正则表达式模式与字符串匹配的次数。其语法为 regexp_count(string, pattern [, start [, flags ]])。patternstring 中搜索,通常从字符串开头开始,但如果提供了 start 参数,则从该字符索引开始。flags 参数是一个可选的文本字符串,包含零个或多个单字母标志,用于更改函数行为。例如,在 flags 中包含 i 指定了不区分大小写的匹配。支持的标志在 表 9.24 中描述。

一些例子

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 ]]]]]).patternstring 中搜索,通常从字符串开头开始,但如果提供了 start 参数,则从该字符索引开始。如果指定了 N,则找到模式的第 N 次匹配,否则找到第一次匹配。如果 endoption 参数被省略或指定为零,则函数返回匹配的第一个字符的位置。否则,endoption 必须是 1,函数返回匹配结束后的字符位置。flags 参数是一个可选的文本字符串,包含零个或多个单字母标志,用于更改函数行为。支持的标志在 表 9.24 中描述。对于包含括号子表达式的模式,subexpr 是一个整数,指示哪个子表达式是感兴趣的:结果标识与该子表达式匹配的子字符串的位置。子表达式按其左括号的顺序编号。当 subexpr 被省略或为零时,结果标识整个匹配的位置,而不考虑括号子表达式。

一些例子

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 正则表达式模式的匹配是否发生在字符串中,返回布尔 true 或 false。其语法为 regexp_like(string, pattern [, flags ])。flags 参数是一个可选的文本字符串,包含零个或多个单字母标志,用于更改函数行为。支持的标志在 表 9.24 中描述。如果未指定标志,此函数的结果与 ~ 操作符相同。如果仅指定了 i 标志,则其结果与 ~* 操作符相同。

一些例子

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 个元素是与模式的第 n 个括号子表达式匹配的子字符串(不包括“非捕获”括号;有关详细信息,请参阅下文)。flags 参数是一个可选的文本字符串,包含零个或多个单字母标志,用于更改函数行为。支持的标志在 表 9.24 中描述。

一些例子

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 行。返回的每一行都是一个文本数组,包含与整个匹配模式或模式的括号子表达式匹配的子字符串,就像上面为 regexp_match 所描述的那样。regexp_matches 接受 表 9.24 中显示的所有标志,再加上 g 标志,该标志命令它返回所有匹配项,而不仅仅是第一个。regexp_matches 接受 表 9.24 中显示的 g 标志,用于命令它返回所有匹配项,而不仅仅是第一个。

一些例子

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 个括号子表达式匹配的源子字符串,并且它可以包含 \& 来表示应插入与整个模式匹配的子字符串。如果要将字面反斜杠放入替换文本中,请编写 \\patternstring 中搜索,通常从字符串开头开始,但如果提供了 start 参数,则从该字符索引开始。默认情况下,只替换模式的第一次匹配。如果指定了 N 且大于零,则替换模式的第 N 次匹配。如果给出了 g 标志,或者指定了 N 且为零,则替换所有在 start 位置或之后的匹配。(当指定 N 时,g 标志被忽略。)flags 参数是一个可选的文本字符串,包含零个或多个单字母标志,用于更改函数行为。支持的标志(但不是 g)在 表 9.24 中描述。

一些例子

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 支持 表 9.24 中描述的标志。

函数 regexp_split_to_array 的行为与 regexp_split_to_table 相同,但 regexp_split_to_arraytext 数组的形式返回其结果。其语法为 regexp_split_to_array(string, pattern [, flags ])。参数与 regexp_split_to_table 的参数相同。

一些例子

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)

正如最后一个示例所示,regexp 分割函数会忽略出现在字符串开头或结尾,或紧跟在先前匹配之后的零长度匹配。这与其他 regexp 函数实现的严格的 regexp 匹配定义相反,但在实际情况中通常是最方便的行为。Perl 等其他软件系统也使用类似的定义。

函数 regexp_substr 返回匹配 POSIX 正则表达式模式的子字符串,如果没有匹配则返回 NULL。其语法为 regexp_substr(string, pattern [, start [, N [, flags [, subexpr ]]]]).patternstring 中搜索,通常从字符串开头开始,但如果提供了 start 参数,则从该字符索引开始。如果指定了 N,则返回模式的第 N 次匹配,否则返回第一次匹配。 flags 参数是一个可选的文本字符串,包含零个或多个单字母标志,用于更改函数行为。支持的标志在 表 9.24 中描述。对于包含括号子表达式的模式,subexpr 是一个整数,指示哪个子表达式是感兴趣的:结果是与该子表达式匹配的子字符串。子表达式按其左括号的顺序编号。当 subexpr 被省略或为零时,结果是整个匹配,而不考虑括号子表达式。

一些例子

regexp_substr('number of your street, town zip, FR', '[^,]+', 1, 2)
                                    town zip
regexp_substr('ABCDEFGHI', '(c..)(...)', 1, 1, 'i', 2)
                                   FGH

9.7.3.1. 正则表达式详细信息 #

PostgreSQL 的正则表达式实现使用了 Henry Spencer 编写的一个软件包。下面关于正则表达式的描述大部分直接摘自他的手册。

正则表达式(REs),如POSIX1003.2 中定义,有两种形式:扩展REs 或EREs(大致相当于 egrep 的格式),和基本REs 或BREs(大致相当于 ed 的格式)。PostgreSQL 支持这两种形式,并且还实现了 POSIX 标准中没有但由于在 Perl 和 Tcl 等编程语言中可用而广泛使用的某些扩展。REs 使用这些非 POSIX 扩展在本文档中被称为高级REs 或AREs。AREs 几乎是 EREs 的精确超集,但 BREs 有几个表示法上的不兼容之处(而且功能也大大受限)。我们首先描述 ARE 和 ERE 形式,并指出仅适用于 ARE 的特性,然后描述 BRE 的区别。

注意

PostgreSQL 最初总是假定正则表达式遵循 ARE 规则。然而,可以通过在 RE 模式前面加上一个嵌入式选项来选择更有限的 ERE 或 BRE 规则,如 第 9.7.3.4 节中所述。这对于与期望严格遵循POSIX1003.2 规则的应用程序兼容非常有用。

正则表达式被定义为一个或多个由 | 分隔的分支。它匹配可以匹配其中一个分支的任何内容。

一个分支是由零个或多个量化原子约束连接而成。它匹配第一个匹配项,后跟第二个匹配项,依此类推;空分支匹配空字符串。

一个量化原子是可能后面跟着一个量词原子。没有量词时,它匹配原子的匹配。有量词时,它可以匹配该原子的一些匹配次数。表 9.17 中显示了可能的原子及其选项。可能的量词及其含义显示在 表 9.18 中。

一个约束匹配一个空字符串,但仅在满足特定条件时才匹配。约束可以用在原子可以使用的任何地方,除了它后面不能跟着量词。表 9.19 中显示了简单的约束;更多约束将在后面描述。

表 9.17. 正则表达式原子

原子 描述
(re) (其中 re 是任何正则表达式) 匹配 re 的一个匹配项,该匹配项被记录以供可能报告
(?:re) 如上所述,但匹配项不被记录以供报告(一对“非捕获”括号)(仅限 ARE)
. 匹配任何单个字符
[chars] 一个 方括号表达式,匹配 chars 中的任何一个字符(有关更多详细信息,请参见 第 9.7.3.2 节
\k (其中 k 是一个非字母数字字符)匹配该字符作为普通字符,例如 \\ 匹配一个反斜杠字符
\c 其中 c 是字母数字(可能后跟其他字符)是一个 转义,请参见 第 9.7.3.3 节(仅限 ARE;在 ERE 和 BRE 中,这匹配 c
{ 后面跟一个非数字字符时,匹配左大括号字符 {;后面跟一个数字时,它是 bound 的开头(见下文)
x 其中 x 是一个没有其他意义的单个字符,匹配该字符

RE 不能以反斜杠(\)结尾。

注意

如果 standard_conforming_strings 设置为 off,那么在字面字符串常量中写入的任何反斜杠都需要加倍。有关更多信息,请参阅 第 4.1.2.1 节

表 9.18. 正则表达式量词

量词 匹配
* 原子出现 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 中可用)匹配与其对应的普通(贪婪)量词相同的可能性,但偏好最少匹配次数而不是最多匹配次数。有关更多详细信息,请参见 第 9.7.3.5 节

注意

一个量词不能紧跟另一个量词,例如 ** 是无效的。量词不能出现在表达式或子表达式的开头,也不能跟在 ^| 之后。

表 9.19. 正则表达式约束

约束 描述
^ 匹配字符串的开头
$ 匹配字符串的结尾
(?=re) 正向先行断言 在匹配 re 的子字符串开始的任何点进行匹配(仅限 ARE)
(?!re) 负向先行断言 在没有匹配 re 的子字符串开始的任何点进行匹配(仅限 ARE)
(?<=re) 正向后行断言 在匹配 re 的子字符串结束的任何点进行匹配(仅限 ARE)
(?<!re) 负向后行断言 在没有匹配 re 的子字符串结束的任何点进行匹配(仅限 ARE)

先行断言和后行断言不能包含 反向引用(参见 第 9.7.3.3 节),并且其中的所有括号都被视为非捕获。

9.7.3.2. 方括号表达式 #

方括号表达式 是由 [] 包围的字符列表。它通常匹配列表中的任何单个字符(但请参见下文)。如果列表以 ^ 开头,则它匹配除列表其余部分之外的任何单个字符。如果列表中的两个字符被 - 分隔,这是介于这两个字符之间(含)的字符的完整范围的简写,具体取决于排序顺序,例如 [0-9]ASCII匹配任何十进制数字。两个范围共享一个端点是非法的,例如 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 字符是否属于这些类之一取决于用于正则表达式函数或运算符的 排序规则(参见 第 23.2 节),或者默认情况下数据库的 LC_CTYPE 区域设置(参见 第 23.1 节)。非 ASCII 字符的分类在不同平台上可能不同,即使是在名称相似的区域设置中。(但 C 区域设置从不认为任何非 ASCII 字符属于这些类中的任何一个。)除了这些标准字符类之外,PostgreSQL 还定义了 word 字符类,它与 alnum 加上下划线(_)字符相同,以及 ascii 字符类,它只包含 7 位 ASCII 集合。

有两个特殊的方括号表达式:方括号表达式 [[:<:]][[:>:]] 是约束,分别匹配单词开头和结尾的空字符串。单词定义为一系列单词字符,这些字符既不被单词字符 precede 也不被单词字符 follow。单词字符是属于 word 字符类的任何字符,即任何字母、数字或下划线。这是对 1003.2 的扩展,与之兼容但未在其中指定,应谨慎用于打算移植到其他系统的软件。下面描述的约束转义通常更可取;它们不比标准更标准,但输入更方便。POSIX9.7.3.3. 正则表达式转义 #

转义 是以 \ 开头后跟一个字母数字字符的特殊序列。转义有几种类型:字符输入、类简写、约束转义和反向引用。在 ARE 中,以 \ 开头后跟字母数字字符但不是有效转义的序列是非法的。在 ERE 中,没有转义:在方括号表达式之外,\ 后面跟一个字母数字字符只是表示该字符作为普通字符,而在方括号表达式内部,\ 是一个普通字符。(后者是 ERE 和 ARE 之间的一个实际不兼容之处。)

字符输入转义 旨在方便在 RE 中指定非打印字符和其他不方便的字符。它们显示在 表 9.20 中。

类简写转义 为某些常用的字符类提供了简写。它们显示在 表 9.21 中。

一个 约束转义 是一个约束,如果满足特定条件,则匹配空字符串,它被写成一个转义。它们显示在 表 9.22 中。

一个 反向引用\n)匹配由数字 n 指定的先前圆括号括起来的子表达式匹配的相同字符串(参见 表 9.23)。例如,([bc])\1 匹配 bbcc,但不匹配 bccb。子表达式必须完全出现在 RE 中的反向引用之前。子表达式按其前导括号的顺序编号。非捕获括号不定义子表达式。反向引用仅考虑由被引用子表达式匹配的字符串字符,而不考虑其中的任何约束。例如,(^\d)\1 将匹配 22

表 9.20. 正则表达式字符输入转义

\a

转义 描述
警报(响铃)字符,如 C 中 退格,如 C 中
\b \B
反斜杠(\)的同义词,以帮助减少反斜杠加倍的需求 \cX
(其中 X 是任何字符)低 5 位与 X 相同,其他位全为零的字符 \e
排序名称为 ESC 的字符,或者在没有该名称的情况下,值为八进制 033 的字符 换页符,如 C 中
\f 换行符,如 C 中
\n 回车符,如 C 中
\r 水平制表符,如 C 中
\t \uwxyz
(其中 wxyz 是正好四个十六进制数字)值为 0xwxyz 的字符 \Ustuvwxyz
(其中 stuvwxyz 是正好八个十六进制数字)值为 0xstuvwxyz 的字符 \v
垂直制表符,如 C 中 \xhhh
(其中 hhh 是任何十六进制数字序列)值为 0xhhh 的字符(无论有多少十六进制数字,都表示一个字符) 值为 0(空字节)的字符
\0 \xy
(其中 xy 是正好两个八进制数字,并且不是 反向引用)值为八进制 0xy 的字符 \xyz
(其中 xyz 是正好三个八进制数字,并且不是 反向引用)值为八进制 0xyz 的字符 十六进制数字是 0-9a-fA-F。八进制数字是 0-7

指定值超出 ASCII 范围(0-127)的数字字符输入转义具有依赖于数据库编码的含义。当编码为 UTF-8 时,转义值等同于 Unicode 代码点,例如 \u1234 表示字符 U+1234。对于其他多字节编码,字符输入转义通常只指定字符的字节值的串联。如果转义值不对应于数据库编码中的任何合法字符,则不会引发错误,但它永远不会匹配任何数据。

字符输入转义始终被视为普通字符。例如,在 ASCII 中 \135],但 \135 不会终止方括号表达式。

表 9.21. 正则表达式类简写转义

\d

转义 描述
匹配任何数字,类似于 [[:digit:]] \s
匹配任何空白字符,类似于 [[:space:]] \w
匹配任何单词字符,类似于 [[:word:]] \D
匹配任何非数字字符,类似于 [^[:digit:]] \S
匹配任何非空白字符,类似于 [^[:space:]] \W
匹配任何非单词字符,类似于 [^[:word:]] 类简写转义在方括号表达式内部也有效,尽管上面显示的定义在那种上下文中并不完全符合语法。例如,[a-c\d] 等同于 [a-c[:digit:]]

表 9.22. 正则表达式约束转义

\A

转义 描述
仅在字符串开头匹配(关于这与 ^ 有何不同,请参见 第 9.7.3.5 节 \m
仅在单词开头匹配 \M
仅在单词结尾匹配 \y
仅在单词开头或结尾匹配 \Y
仅在非单词开头或结尾的点匹配 \Z
仅在字符串结尾匹配(关于这与 $ 有何不同,请参见 第 9.7.3.5 节 单词的定义与上面 [[:<:]][[:>:]] 的说明相同。约束转义在方括号表达式内是非法的。

表 9.23. 正则表达式反向引用

\

转义 描述
m (其中 m 是非零数字)对第 m 个子表达式的反向引用
\mnn (其中 m 是非零数字,nn 是更多数字,并且十进制值 mnn 不大于迄今为止看到的捕获括号的数量)对第 mnn 个子表达式的反向引用

注意

八进制字符输入转义和反向引用之间存在固有歧义,以下面的启发式方法解决,如上所述。前导零始终表示八进制转义。单个非零数字,后面没有其他数字,始终被视为反向引用。非零开头的多位数序列,如果出现在合适的子表达式之后(即,数字在反向引用的合法范围内),则被视为反向引用,否则被视为八进制。

9.7.3.4. 正则表达式元语法 #

除了上面描述的主要语法之外,还有一些特殊形式和杂项语法功能可用。

RE 可以以两个特殊 指令 前缀之一开头。如果 RE 以 ***: 开头,则 RE 的其余部分被视为 ARE。(这通常在 PostgreSQL 中没有影响,因为 RE 被假定为 ARE;但如果 flags 参数指定了 ERE 或 BRE 模式,则有影响。)如果 RE 以 ***= 开头,则 RE 的其余部分被视为字面字符串,所有字符都视为普通字符。

ARE 可以以 嵌入式选项 开头:序列 (?xyz)(其中 xyz 是一个或多个字母字符)指定影响 RE 其余部分(的)选项。这些选项覆盖任何先前确定的选项 — 特别是,它们可以覆盖由 regex 运算符隐含的区分大小写行为,或 regex 函数的 flags 参数。可用的选项字母显示在 表 9.24 中。请注意,这些相同的选项字母用于 regex 函数的 flags 参数。

表 9.24. ARE 嵌入式选项字母

选项 描述
b RE 的其余部分是 BRE
c 区分大小写匹配(覆盖运算符类型)
e RE 的其余部分是 ERE
i 不区分大小写匹配(参见 第 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 节
x 展开语法(见下文)

嵌入式选项在终止序列的 ) 处生效。它们只能出现在 ARE 的开头(如果存在 ***: 指令)。

除了通常的(紧凑)RE 语法(其中所有字符都具有意义)之外,还有一种 展开 语法,可通过指定嵌入式 x 选项获得。在展开语法中,RE 中的空白字符以及 # 和随后的换行符(或 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 作为整体是非贪婪的,因为 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,""}

这也行不通,因为现在整个正则表达式都是非贪婪的,所以它会尽快结束整个匹配。我们可以通过强制整个正则表达式贪婪来达到我们的目的。

SELECT regexp_match('abc01234xyz', '(?:(.*?)(\d+)(.*)){1,1}');
Result: {abc,01234,xyz}

将整个正则表达式的贪婪度与其组件的贪婪度分开控制,可以为处理可变长度模式提供极大的灵活性。

在决定什么是一个更长或更短的匹配时,匹配长度是以字符而不是排序元素来衡量的。空字符串比完全没有匹配更长。例如:bb* 匹配 abbbc 的中间三个字符;(week|wee)(night|knights) 匹配 weeknights 的全部十个字符;当 (.*).*abc 匹配时,括号括起来的子表达式匹配全部三个字符;当 (a*)*bc 匹配时,整个正则表达式和括号括起来的子表达式都匹配一个空字符串。

如果指定了不区分大小写的匹配,效果就好像字母表中的所有大小写区别都已消失一样。当一个存在于多种大小写的字母作为普通字符出现在括号表达式之外时,它实际上被转换成一个包含两种大小写的括号表达式,例如 x 变成 [xX]。当它出现在括号表达式内部时,它的所有大小写对应项都会被添加到括号表达式中,例如 [x] 变成 [xX],而 [^x] 变成 [^xX]

如果指定了换行敏感匹配,. 和使用 ^ 的括号表达式将永远不会匹配换行符(因此除非正则表达式显式包含换行符,否则匹配不会跨越多行),并且 ^$ 将分别匹配换行符之后和之前的空字符串,此外还将分别匹配字符串的开头和结尾。但 ARE 转义符 \A\Z 继续匹配字符串的开头或结尾。此外,字符类简写 \D\W 将匹配换行符,而不管此模式如何。(在 PostgreSQL 14 之前,它们在换行敏感模式下不匹配换行符。要获得旧的行为,请写入 [^[:digit:]][^[:word:]]。)

如果指定了部分换行敏感匹配,这将像换行敏感匹配一样影响 . 和括号表达式,但不影响 ^$

如果指定了反向部分换行敏感匹配,这将像换行敏感匹配一样影响 ^$,但不影响 . 和括号表达式。这不太有用,但为了对称性而提供。

9.7.3.6. 限制和兼容性 #

在此实现中,对正则表达式的长度没有施加任何特定限制。但是,旨在高度可移植的程序不应使用长度超过 256 字节的正则表达式,因为符合 POSIX 的实现可以拒绝接受此类正则表达式。

ARE 中唯一与 POSIX ERE 实际不兼容的特性是 \ 在括号表达式内部不会失去其特殊意义。所有其他 ARE 特性都使用 POSIX ERE 中非法或具有未定义或未指定效果的语法;导演的 *** 语法同样超出了 BRE 和 ERE 的 POSIX 语法。

许多 ARE 扩展都借鉴于 Perl,但其中一些已被修改以使其更清晰,并且缺少一些 Perl 扩展。值得注意的不兼容性包括 \b\B、缺少对尾随换行符的特殊处理、将反向括号表达式添加到受换行敏感匹配影响的项目中、前瞻/后顾约束中的括号和反向引用限制,以及最长/最短匹配(而不是首次匹配)匹配语义。

9.7.3.7. 基本正则表达式 #

BRE 在几个方面与 ERE 不同。在 BRE 中,|+? 是普通字符,并且没有等效功能。边界的定界符是 \{\},而 {} 本身是普通字符。嵌套子表达式的括号是 \(\),而 () 本身是普通字符。^ 是一个普通字符,除非它位于 RE 的开头或括号括起来的子表达式的开头,$ 是一个普通字符,除非它位于 RE 的结尾或括号括起来的子表达式的结尾,并且 * 是一个普通字符,如果它出现在 RE 的开头或括号括起来的子表达式的开头(在可能的起始 ^ 之后)。最后,提供了一位数字的反向引用,并且 \<\>[[:<:]][[:>:]] 的同义词;在 BRE 中没有其他转义符可用。

9.7.3.8. 与 SQL 标准和 XQuery 的区别 #

自 SQL:2008 起,SQL 标准就包含了正则表达式运算符和函数,这些运算符和函数按照 XQuery 正则表达式标准执行模式匹配。

  • LIKE_REGEX

  • OCCURRENCES_REGEX

  • POSITION_REGEX

  • SUBSTRING_REGEX

  • TRANSLATE_REGEX

PostgreSQL 目前不实现这些运算符和函数。您可以在每种情况下获得近似等效的功能,如 表 9.25 所示。(表中省略了双方的各种可选子句。)

表 9.25. 正则表达式函数等效性

SQL 标准 PostgreSQL
字符串 LIKE_REGEX 模式 regexp_like(字符串, 模式)字符串 ~ 模式
OCCURRENCES_REGEX(模式 IN 字符串) regexp_count(字符串, 模式)
POSITION_REGEX(模式 IN 字符串) regexp_instr(字符串, 模式)
SUBSTRING_REGEX(模式 IN 字符串) regexp_substr(字符串, 模式)
TRANSLATE_REGEX(模式 IN 字符串 WITH 替换) 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(参见 表 9.21)(您可以通过将 COLLATE 子句附加到运算符或函数来控制)。XQuery 通过引用 Unicode 字符属性来指定这些类,因此只有在遵循 Unicode 规则的区域设置中才能获得等效行为。

  • SQL 标准(而不是 XQuery 本身)尝试处理比 POSIX 更多的“换行符”变体。上面描述的换行敏感匹配选项仅将 ASCII NL (\n) 视为换行符,但 SQL 要求我们也将其视为 CR (\r)、CRLF (\r\n)(Windows 风格的换行符)以及一些仅限 Unicode 的字符,如行分隔符 (U+2028)。值得注意的是,根据 SQL,.\s 应将 \r\n 计为一个字符而不是两个。

  • 表 9.20 中描述的字符输入转义符中,XQuery 仅支持 \n\r\t

  • XQuery 不支持括号表达式中的字符类 [:name:] 语法。

  • XQuery 没有前瞻或后顾约束,也没有 表 9.22 中描述的任何约束转义符。

  • XQuery 中不存在 第 9.7.3.4 节 中描述的元语法形式。

  • XQuery 定义的正则表达式标志字母与 POSIX 的选项字母(表 9.24)相关,但不相同。虽然 iq 选项行为相同,但其他选项不同。

    • XQuery 的 s(允许点匹配换行符)和 m(允许 ^$ 匹配换行符)标志提供了与 POSIX 的 npw 标志相同的行为,但它们 匹配 POSIX 的 sm 标志的行为。特别要注意的是,点匹配换行符是 POSIX 中的默认行为,但在 XQuery 中不是。

    • XQuery 的 x(忽略模式中的空白字符)标志与 POSIX 的扩展模式标志明显不同。POSIX 的 x 标志还允许 # 开始模式中的注释,并且 POSIX 不会忽略反斜杠后的空白字符。

提交更正

如果您在文档中看到任何不正确的内容、与您对特定功能的体验不符或需要进一步澄清的内容,请使用 此表单 报告文档问题。