首页 / 字符串
REGEXP_EXTRACT 正则提取
REGEXP_EXTRACT 用正则表达式匹配字符串,返回指定分组的内容。除 Hologres 外都同名可用,但分组参数是否必填、没有匹配时返回空字符串还是 NULL、正则语法和反斜杠转义都有差异。Hologres 要用 REGEXP_MATCH 加数组下标改写。
各引擎写法
| 引擎 | 支持 | 写法 | 说明 | 依据 |
|---|---|---|---|---|
| MaxCompute | 支持 | REGEXP_EXTRACT(source, pattern[, group_id]) | group_id 默认为 1,为 0 时返回整个匹配。pattern 没有分组且不传 group_id 时会报错。Hive 兼容数据类型版本遵循 Java 正则规范,1.0 和 2.0 数据类型版本遵循 MaxCompute 自己的规范。 | 官方文档 |
| Hologres | 需改写 | (REGEXP_MATCH(str, pattern))[n] | 字符串函数中没有 REGEXP_EXTRACT。REGEXP_MATCH 返回由各分组组成的数组,再用数组下标取第 n 组,下标从 1 开始。 | 官方文档 |
| StarRocks | 支持 | regexp_extract(str, pattern, pos) | pos 是必填参数。没有匹配时返回空字符串。 | 官方文档 |
| Doris | 支持 | REGEXP_EXTRACT(str, pattern, pos) | pos 是必填参数。没有匹配时返回空字符串。默认使用 RE2 正则语法,不支持零宽断言;把会话变量 enable_extended_regex 设为 true 后才支持。 | 官方文档 |
| Hive | 支持 | regexp_extract(subject, pattern, index) | 签名中 index 是必填参数,含义与 Java Matcher.group() 的下标相同。文档提醒 '\s' 匹配的是字母 s,匹配空白要写 '\\s'。 | 官方文档 |
| Spark SQL | 支持 | regexp_extract(str, regexp[, idx]) | Spark 1.5.0 起提供。idx 默认为 1,为 0 时返回整个匹配。使用 Java 正则,字符串字面量会先被 SQL 解析器反转义,文档建议用 r 前缀的原始字符串,例如 r'(\d+)'。 | 官方文档 |
| Flink SQL | 支持 | REGEXP_EXTRACT(string1, string2[, integer]) | 分组下标从 1 开始,0 表示整个匹配,下标不能超过定义的分组数。 | 官方文档 |
迁移注意事项
- 第三个参数是否必填不一样:MaxCompute、Spark 和 Flink 可以省略,默认取第 1 组;StarRocks、Doris 和 Hive 必须写上。迁移时统一写出分组下标最稳妥。
- 没有匹配时的返回值不同:StarRocks 和 Doris 文档写明返回空字符串,MaxCompute 只写明参数为 NULL 时返回 NULL。下游用 IS NULL 判断的逻辑迁移后要实测。
- MaxCompute 的 pattern 没有分组且不传 group_id 时直接报错,例如 REGEXP_EXTRACT('foothebar', 'thebar')。要么给 pattern 加括号,要么传 0。
- 反斜杠转义各引擎不同。MaxCompute 文档要求在客户端写两个反斜杠,Spark 文档建议用 r'' 原始字符串。示例里用 [0-9] 代替 \d,可以避开转义差异。
- Doris 默认用 RE2 语法,不支持 (?=...) 这类零宽断言。从 Hive 或 Spark 的 Java 正则迁移过来时,需要先确认是否用到这些写法。
示例
从 URL 参数中取 order_id
SELECT REGEXP_EXTRACT(url, 'order_id=([0-9]+)', 1) AS order_id FROM access_log;SELECT (REGEXP_MATCH(url, 'order_id=([0-9]+)'))[1] AS order_id FROM access_log;SELECT regexp_extract(url, 'order_id=([0-9]+)', 1) AS order_id FROM access_log;SELECT REGEXP_EXTRACT(url, 'order_id=([0-9]+)', 1) AS order_id FROM access_log;SELECT regexp_extract(url, 'order_id=([0-9]+)', 1) AS order_id FROM access_log;SELECT regexp_extract(url, 'order_id=([0-9]+)', 1) AS order_id FROM access_log;SELECT REGEXP_EXTRACT(url, 'order_id=([0-9]+)', 1) AS order_id FROM access_log;