跳到主要内容

正则表达式

Goose 提供模式匹配运算符 (LIKE, SIMILAR TO, GLOB), 也通过函数支持正则表达式。

正则表达式语法

Goose 使用 RE2 库 作为正则表达式引擎。关于正则语法,请参阅 RE2 文档

函数

所有函数都接受一组可选选项

名称描述
regexp_extract(string, pattern[, group = 0][, options])string 包含正则模式 pattern,返回可选参数 group 指定的捕获组;否则返回空字符串。group 必须是常量值。若未提供 group,默认值为 0。可设置一组选项 options
regexp_extract(string, pattern, name_list[, options])string 包含正则模式 pattern,返回以 name_list 中名称命名字段的结构体(包含捕获组);否则返回具有相同键、值均为空字符串的结构体。
regexp_extract_all(string, regex[, group = 0][, options])查找 string 中与 regex 不重叠的所有匹配,并返回对应 group 的值。
regexp_full_match(string, regex[, options])若整个 string 都匹配 regex,返回 true
regexp_matches(string, pattern[, options])string 包含正则模式 pattern,返回 true,否则返回 false
regexp_replace(string, pattern, replacement[, options])string 包含正则模式 pattern,将匹配部分替换为 replacement。默认仅替换第一个匹配。可设置一组选项 options,包括全局标志 g
regexp_split_to_array(string, regex[, options])string_split_regex 的别名。按 regex 拆分 string
regexp_split_to_table(string, regex[, options])regex 拆分 string,并为每一部分返回一行。

regexp_extract(string, pattern[, group = 0][, options])

| Description | 若 string 包含正则模式 pattern,返回可选参数 group 指定的捕获组;否则返回空字符串。group 必须是常量值。若未提供 group,默认值为 0。可设置一组选项 options。 | | Example | regexp_extract('abc', '([a-z])(b)', 1) | | Result | a |

regexp_extract(string, pattern, name_list[, options])

| Description | 若 string 包含正则模式 pattern,返回以 name_list 中名称命名字段的结构体(包含捕获组);否则返回具有相同键、值均为空字符串的结构体。可设置一组选项 options。 | | Example | regexp_extract('2023-04-15', '(\d+)-(\d+)-(\d+)', ['y', 'm', 'd']) | | Result | {'y':'2023', 'm':'04', 'd':'15'} |

regexp_extract_all(string, regex[, group = 0][, options])

| Description | 查找 string 中与 regex 不重叠的所有匹配,并返回对应 group 的值。可设置一组选项 options。 | | Example | regexp_extract_all('Peter: 33, Paul:14', '(\w+):\s*(\d+)', 2) | | Result | [33, 14] |

regexp_full_match(string, regex[, options])

| Description | 若整个 string 都匹配 regex,返回 true。可设置一组选项 options。 | | Example | regexp_full_match('anabanana', '(an)*') | | Result | false |

regexp_matches(string, pattern[, options])

| Description | 若 string 包含正则模式 pattern,返回 true,否则返回 false。可设置一组选项 options。 | | Example | regexp_matches('anabanana', '(an)*') | | Result | true |

regexp_replace(string, pattern, replacement[, options])

| Description | 若 string 包含正则模式 pattern,将匹配部分替换为 replacement。默认仅替换第一个匹配。可设置一组选项 options,包括全局标志 g。 | | Example | regexp_replace('hello', '[lo]', '-') | | Result | he-lo |

regexp_split_to_array(string, regex[, options])

| Description | string_split_regex 的别名。按 regex 拆分 string。可设置一组选项 options。 | | Example | regexp_split_to_array('hello world; 42', ';? ') | | Result | ['hello', 'world', '42'] |

regexp_split_to_table(string, regex[, options])

| Description | 按 regex 拆分 string,并为每一部分返回一行。可设置一组选项 options。 | | Example | regexp_split_to_table('hello world; 42', ';? ') | | Result | Three rows: 'hello', 'world', '42' |

regexp_matches 函数与 SIMILAR TO 运算符类似,但它不要求整个字符串都匹配。只要字符串包含该模式,regexp_matches 就会返回 true(除非使用特殊符号 ^$ 将正则锚定到字符串开头和结尾)。示例如下:

SELECT regexp_matches('abc', 'abc');       -- true
SELECT regexp_matches('abc', '^abc$'); -- true
SELECT regexp_matches('abc', 'a'); -- true
SELECT regexp_matches('abc', '^a$'); -- false
SELECT regexp_matches('abc', '.*(b|d).*'); -- true
SELECT regexp_matches('abc', '(b|c).*'); -- true
SELECT regexp_matches('abc', '^(b|c).*'); -- false
SELECT regexp_matches('abc', '(?i)A'); -- true
SELECT regexp_matches('abc', 'A', 'i'); -- true

正则表达式函数选项

正则函数支持以下 options

选项描述
'c'区分大小写匹配
'i'不区分大小写匹配
'l'按字面值匹配,而非正则标记
'm', 'n', 'p'对换行敏感的匹配
'g'全局替换,仅适用于 regexp_replace
's'对换行不敏感的匹配

例如:

SELECT regexp_matches('abcd', 'ABC', 'c'); -- false
SELECT regexp_matches('abcd', 'ABC', 'i'); -- true
SELECT regexp_matches('ab^/$cd', '^/$', 'l'); -- true
SELECT regexp_matches(E'hello\nworld', 'hello.world', 'p'); -- false
SELECT regexp_matches(E'hello\nworld', 'hello.world', 's'); -- true

使用 regexp_matches

在可能的情况下,regexp_matches 会被优化为 LIKE 运算符。为获得最佳性能,若适用应传入 'c' 选项(区分大小写匹配)。注意:默认情况下,RE2中的 . 不匹配换行符。

原始表达式优化后等价表达式
regexp_matches('hello world', '^hello', 'c')prefix('hello world', 'hello')
regexp_matches('hello world', 'world$', 'c')suffix('hello world', 'world')
regexp_matches('hello world', 'hello.world', 'c')LIKE 'hello_world'
regexp_matches('hello world', 'he.*rld', 'c')LIKE '%he%rld'

使用 regexp_replace

regexp_replace 函数用于将字符串中匹配正则模式的部分替换为指定替换字符串。在替换字符串中可使用 \dd 为表示分组编号的数字)来引用正则捕获组。注意默认情况下,regexp_replace 仅替换第一个匹配项。若要替换所有匹配项,请使用全局替换标志(g)。

regexp_replace 使用示例:

SELECT regexp_replace('abc', '(b|c)', 'X');        -- aXc
SELECT regexp_replace('abc', '(b|c)', 'X', 'g'); -- aXX
SELECT regexp_replace('abc', '(b|c)', '\1\1\1\1'); -- abbbbc
SELECT regexp_replace('abc', '(.*)c', '\1e'); -- abe
SELECT regexp_replace('abc', '(a)(b)', '\2\1'); -- bac

使用 regexp_extract

regexp_extract 函数用于提取字符串中匹配正则模式的部分。 可通过 group 参数提取模式中的特定捕获组。若未指定 group,默认值为 0,即提取第一个匹配(整个模式)。

SELECT regexp_extract('abc', '.b.');           -- abc
SELECT regexp_extract('abc', '.b.', 0); -- abc
SELECT regexp_extract('abc', '.b.', 1); -- (empty)
SELECT regexp_extract('abc', '([a-z])(b)', 1); -- a
SELECT regexp_extract('abc', '([a-z])(b)', 2); -- b

regexp_extract 还支持 name_list 参数,它是字符串 LIST。使用 name_list 时,regexp_extract 会将对应捕获组作为 STRUCT 字段返回:

SELECT regexp_extract('2023-04-15', '(\d+)-(\d+)-(\d+)', ['y', 'm', 'd']);
{'y': 2023, 'm': 04, 'd': 15}
SELECT regexp_extract('2023-04-15 07:59:56', '^(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)', ['y', 'm', 'd']);
{'y': 2023, 'm': 04, 'd': 15}
SELECT regexp_extract('goose_0_7_1', '^(\w+)_(\d+)_(\d+)', ['tool', 'major', 'minor', 'fix']);
Binder Error:
Not enough group names in regexp_extract

如果列名数量少于捕获组数量,则只返回前面的捕获组。 如果列名数量多于捕获组数量,则会报错。

限制

正则表达式仅支持 9 个捕获组:\1\2\3、...、\9。 不支持两位及以上编号的捕获组。