Hive 正则函数详解与示例

Hive 正则函数详解与示例

目录

  1. 概述
  2. [Hive 中的正则表达式基础](#Hive 中的正则表达式基础)
    2.1 元字符速查
    2.2 捕获组与非捕获组
    2.3 [⚠️ 双重转义规则(核心难点)](#⚠️ 双重转义规则(核心难点))
  3. 正则函数详解与示例
    3.1 [RLIKE / REGEXP -- 模式匹配](#RLIKE / REGEXP – 模式匹配)
    3.2 [REGEXP_EXTRACT -- 提取首个匹配](#REGEXP_EXTRACT – 提取首个匹配)
    3.3 [REGEXP_EXTRACT_ALL -- 提取所有匹配(数组)](#REGEXP_EXTRACT_ALL – 提取所有匹配(数组))
    3.4 [REGEXP_REPLACE -- 替换匹配内容](#REGEXP_REPLACE – 替换匹配内容)
    3.5 [REGEXP_COUNT -- 统计匹配次数](#REGEXP_COUNT – 统计匹配次数)
  4. 实战案例
    4.1 [日志解析 -- 提取 IP、状态码](#日志解析 – 提取 IP、状态码)
    4.2 [数据脱敏 -- 手机号、身份证](#数据脱敏 – 手机号、身份证)
    4.3 清洗非数字字符
    4.4 [URL 解析 -- 提取域名和参数](#URL 解析 – 提取域名和参数)
  5. 性能与最佳实践
  6. 常见陷阱与避坑指南
  7. 附录:常用正则表达式模式

1. 概述

Hive 提供了基于 Java 正则表达式 的内置函数,用于处理字符串的匹配、提取、替换和计数。这些函数在数据清洗、日志解析、格式校验、敏感信息脱敏等场景中非常实用。

Hive 中的正则函数包括:

函数名 功能
RLIKE / REGEXP 判断字符串是否匹配正则(返回布尔值)
REGEXP_EXTRACT 提取第一个匹配的子串(支持捕获组)
REGEXP_EXTRACT_ALL 提取所有匹配的子串(返回数组)
REGEXP_REPLACE 替换匹配正则的部分
REGEXP_COUNT 统计匹配正则的次数

注意REGEXP_EXTRACT_ALLREGEXP_COUNT 在 Hive 1.2.0+ 版本才支持,低版本需升级或使用其他方法。


2. Hive 中的正则表达式基础

2.1 元字符速查

元字符 含义 示例
. 任意单个字符(除换行符) a.c 匹配 abca7c
* 前一个元素出现 0 次或多次 ab*c 匹配 acabcabbc
+ 前一个元素出现 1 次或多次 ab+c 匹配 abcabbc,不匹配 ac
? 前一个元素出现 0 次或 1 次 ab?c 匹配 acabc
` `
^ 字符串开头 ^[0-9] 匹配以数字开头的字符串
$ 字符串结尾 [0-9]$ 匹配以数字结尾的字符串
\d 数字 [0-9] \d+ 匹配一个或多个数字
\D 非数字 \D+ 匹配非数字字符
\w 单词字符 [A-Za-z0-9_] \w+ 匹配单词
\W 非单词字符 \W+ 匹配标点、空格等
\s 空白字符(空格、制表符等) \s+ 匹配连续空白
\S 非空白字符 \S+ 匹配非空字符序列

2.2 捕获组与非捕获组

  • 捕获组 ( ):将括号内的匹配内容保存到组中,可通过 $1$2 引用(在 REGEXP_REPLACE 中)或通过 index 参数提取(在 REGEXP_EXTRACT 中)。
  • 非捕获组 (?: ):仅用于分组或量词作用域,不保存匹配内容。

示例:

sql 复制代码
-- 捕获组:提取域名中的主体部分
SELECT REGEXP_EXTRACT('www.example.com', 'www\\.(.*?)\\.com', 1);  -- 返回 'example'

2.3 ⚠️ 双重转义规则(核心难点)

Hive 中,正则表达式是写在字符串里的 ,Hive SQL 解析器会先对字符串进行一层转义,之后正则引擎再解析一次。因此,所有 Java 正则中的反斜杠 \ 在 Hive 中必须写成 \\

你想匹配的字符 Java 正则写法 Hive SQL 中的写法
数字 \d \d '\\d'
点号 .(字面量) \. '\\.'
一个反斜杠 \ \\ '\\\\'
单词边界 \b \b '\\b'

错误示例(忘记转义):

sql 复制代码
SELECT REGEXP_EXTRACT('123abc', '\d+', 0);   -- 报错或返回 NULL

正确写法

sql 复制代码
SELECT REGEXP_EXTRACT('123abc', '\\d+', 0);  -- 返回 '123'

3. 正则函数详解与示例

3.1 RLIKE / REGEXP -- 模式匹配

语法

sql 复制代码
string RLIKE pattern   -- pattern 为正则表达式字符串
string REGEXP pattern  -- 等价于 RLIKE

返回值BOOLEANTRUE / FALSE

示例

示例 1:判断字符串是否为纯数字
sql 复制代码
SELECT '12345' RLIKE '^\\d+$';   -- 返回 TRUE
SELECT '12a45' RLIKE '^\\d+$';   -- 返回 FALSE
示例 2:筛选出邮箱为 @gmail.com 结尾的用户
sql 复制代码
SELECT name, email
FROM users
WHERE email RLIKE '@gmail\\.com$';
示例 3:结合 NOT RLIKE 排除包含特殊字符的昵称
sql 复制代码
SELECT nickname
FROM users
WHERE nickname NOT RLIKE '[!@#$%]';
示例 4:在 CASE WHEN 中使用
sql 复制代码
SELECT comment,
       CASE WHEN comment RLIKE '(垃圾|广告|色情)' THEN '违规'
            ELSE '正常'
       END AS tag
FROM forum_posts;

3.2 REGEXP_EXTRACT -- 提取首个匹配

语法

sql 复制代码
REGEXP_EXTRACT(string subject, string pattern, int index)
  • pattern:正则表达式,可包含捕获组 ()
  • index
    • 0:返回整个匹配的子串
    • 1,2,3...:返回第 N 个捕获组的内容
    • 若未匹配到,返回空字符串 ''

示例

示例 1:提取手机号中间四位
sql 复制代码
SELECT REGEXP_EXTRACT('13812345678', '1(\\d{4})\\d{4}', 1);  -- 返回 '1234'

正则解释:1 后跟 4 个数字(捕获组),再跟 4 个数字(不捕获)。

示例 2:提取 URL 中的域名
sql 复制代码
SELECT REGEXP_EXTRACT('https://www.example.com/path', 'https?://(?:[^/]+\\.)?([^/]+)', 1);
-- 返回 'example.com'
示例 3:提取日期中的年、月、日
sql 复制代码
SELECT REGEXP_EXTRACT('2026-04-16', '(\\d{4})-(\\d{2})-(\\d{2})', 1) AS year,  -- 2026
       REGEXP_EXTRACT('2026-04-16', '(\\d{4})-(\\d{2})-(\\d{2})', 2) AS month, -- 04
       REGEXP_EXTRACT('2026-04-16', '(\\d{4})-(\\d{2})-(\\d{2})', 3) AS day;   -- 16

3.3 REGEXP_EXTRACT_ALL -- 提取所有匹配(数组)

语法

sql 复制代码
REGEXP_EXTRACT_ALL(string subject, string pattern)

返回值array<string>,包含所有匹配 pattern 的子串(注意:该函数不支持捕获组,总是返回整个匹配)。

示例

示例 1:提取字符串中所有数字
sql 复制代码
SELECT REGEXP_EXTRACT_ALL('abc123def456ghi789', '\\d+');
-- 返回 ['123', '456', '789']
示例 2:配合 LATERAL VIEW EXPLODE 展开数组
sql 复制代码
SELECT word
FROM (
    SELECT REGEXP_EXTRACT_ALL('Hello, world! Hive is great.', '\\w+') AS words
) t
LATERAL VIEW EXPLODE(words) w AS word;
-- 返回多行:Hello, world, Hive, is, great
示例 3:提取所有邮箱地址
sql 复制代码
SELECT REGEXP_EXTRACT_ALL('Contact: a@b.com, support@example.org', '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}');
-- 返回 ['a@b.com', 'support@example.org']

3.4 REGEXP_REPLACE -- 替换匹配内容

语法

sql 复制代码
REGEXP_REPLACE(string subject, string pattern, string replacement)
  • subject 中所有匹配 pattern 的子串替换为 replacement
  • replacement 中可以包含 $1$2 引用捕获组的内容

示例

示例 1:手机号脱敏(保留前三后四,中间用 **** 替换)
sql 复制代码
SELECT REGEXP_REPLACE('13812345678', '(\\d{3})\\d{4}(\\d{4})', '$1****$2');
-- 返回 '138****5678'
示例 2:清洗字符串中的非数字字符
sql 复制代码
SELECT REGEXP_REPLACE('订单号:ORD12345,金额:$99.9', '[^0-9]', '');
-- 返回 '12345999'(注意:会连小数点也去掉)
示例 3:将日期格式从 yyyy/MM/dd 转换为 yyyy-MM-dd
sql 复制代码
SELECT REGEXP_REPLACE('2026/04/16', '/', '-');
-- 返回 '2026-04-16'
示例 4:使用捕获组交换位置(如将 last, first 转为 first last
sql 复制代码
SELECT REGEXP_REPLACE('Doe, John', '(\\w+),\\s+(\\w+)', '$2 $1');
-- 返回 'John Doe'

3.5 REGEXP_COUNT -- 统计匹配次数

语法

sql 复制代码
REGEXP_COUNT(string subject, string pattern)

返回值INT,表示 patternsubject 中出现的次数。

示例

示例 1:统计字符串中数字的个数
sql 复制代码
SELECT REGEXP_COUNT('abc123def456', '\\d');   -- 返回 6(每个数字单独计数)
SELECT REGEXP_COUNT('abc123def456', '\\d+');  -- 返回 2("123" 和 "456" 各一次)
示例 2:统计单词个数(按非字母分隔)
sql 复制代码
SELECT REGEXP_COUNT('Hello, world! Hive is powerful.', '\\w+');  -- 返回 5
示例 3:校验密码复杂度(至少包含大写、小写、数字)
sql 复制代码
SELECT password,
       CASE WHEN REGEXP_COUNT(password, '[A-Z]') >= 1
            AND REGEXP_COUNT(password, '[a-z]') >= 1
            AND REGEXP_COUNT(password, '[0-9]') >= 1
            THEN '强' ELSE '弱' END AS pwd_strength
FROM users;

4. 实战案例

4.1 日志解析 -- 提取 IP、状态码

假设有一条 Nginx 日志:
192.168.1.1 - - [16/Apr/2026:10:30:00 +0800] "GET /index.html HTTP/1.1" 200 1024

sql 复制代码
WITH log_line AS (
    SELECT '192.168.1.1 - - [16/Apr/2026:10:30:00 +0800] "GET /index.html HTTP/1.1" 200 1024' AS raw
)
SELECT REGEXP_EXTRACT(raw, '^(\\S+)', 1) AS ip,                        -- IP
       REGEXP_EXTRACT(raw, '\\[(.*?)\\]', 1) AS time_str,              -- 时间
       REGEXP_EXTRACT(raw, '"(.*?)"', 1) AS request,                   -- 请求
       REGEXP_EXTRACT(raw, '\\s(\\d{3})\\s', 1) AS status_code        -- 状态码
FROM log_line;

4.2 数据脱敏 -- 手机号、身份证

sql 复制代码
-- 手机号脱敏:保留前3后4
SELECT REGEXP_REPLACE(mobile, '(\\d{3})\\d{4}(\\d{4})', '$1****$2') AS masked_mobile
FROM users;

-- 身份证脱敏:保留前6后4
SELECT REGEXP_REPLACE(id_card, '(\\d{6})\\d{8}(\\d{4})', '$1********$2') AS masked_id
FROM user_identity;

4.3 清洗非数字字符

从混合字段中提取纯数字(例如提取金额):

sql 复制代码
SELECT REGEXP_REPLACE(price_str, '[^0-9.]', '') AS clean_price
FROM products;
-- 注意:可能保留多个小数点,需要进一步处理

更严谨的金额提取(提取第一个数字或小数):

sql 复制代码
SELECT REGEXP_EXTRACT(price_str, '(\\d+(\\.\\d+)?)', 1) AS amount
FROM products;

4.4 URL 解析 -- 提取域名和参数

sql 复制代码
WITH urls AS (
    SELECT 'https://www.example.com:8080/path?id=123&name=test' AS url
)
SELECT REGEXP_EXTRACT(url, '://([^/]+)', 1) AS domain,   -- www.example.com:8080
       REGEXP_EXTRACT(url, '\\?(.*)', 1) AS params       -- id=123&name=test
FROM urls;

5. 性能与最佳实践

  1. 能用简单函数就不写正则

    • 判断前缀:LIKE 'abc%' 优于 RLIKE '^abc'
    • 提取固定位置:SUBSTR(col, 2, 3) 优于 REGEXP_EXTRACT
  2. 避免在大表的 WHERE 子句中使用复杂正则

    正则匹配消耗 CPU,若必须使用,尽量先用分区或其他条件过滤掉大部分数据。

  3. 警惕灾难性回溯

    复杂的嵌套量词(如 (a+)*b)可能导致匹配时间指数级增长。应使用更具体的正则或拆分逻辑。

  4. 预编译正则(Hive 内部优化)

    Hive 会对常量正则字符串进行预编译,因此尽量将正则写成字面量,而不是由列值动态拼接。

  5. 使用 LATERAL VIEW 配合 REGEXP_EXTRACT_ALL 时注意数据膨胀

    如果数组很大,EXPLODE 会产生大量行,可能降低性能。


6. 常见陷阱与避坑指南

陷阱 说明 解决方案
忘记双重转义 \d 写成 '\\d' 牢记:每个 \\\
REGEXP_EXTRACT 索引超出捕获组 正则中只有 1 个 (),却写 index=2 检查捕获组个数,索引从 1 开始
REGEXP_EXTRACT_ALL 不支持捕获组 该函数总是返回整个匹配,不能单独提取组内内容 若需提取组,可改用 REGEXP_EXTRACT 配合循环或多次调用
NULL 值处理 NULL RLIKE '.*' 返回 NULL 而非 FALSE 使用 COALESCE(col, '') 将 NULL 转为空串
贪婪匹配导致结果过长 '.*' 会匹配尽可能多的字符 使用非贪婪 '.*?' 或明确边界
版本兼容性 低版本 Hive 不支持 REGEXP_COUNTREGEXP_EXTRACT_ALL 升级或使用其他方式(如 LATERAL VIEW + parse_url 等)

7. 附录:常用正则表达式模式

用途 正则表达式(Hive 写法)
手机号(简单) '1[3-9]\\d{9}'
邮箱 '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}'
IPv4 地址 '\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}'
日期 yyyy-MM-dd '\\d{4}-\\d{2}-\\d{2}'
时间 HH:mm:ss '\\d{2}:\\d{2}:\\d{2}'
纯数字 '^\\d+$'
纯字母 '^[A-Za-z]+$'
URL 协议 '^https?://'
HTML 标签 '<[^>]+>'

总结 :掌握 Hive 正则函数的关键在于理解双重转义规则和捕获组的用法。从简单的 RLIKE 匹配,到 REGEXP_EXTRACT 精准提取,再到 REGEXP_REPLACE 脱敏清洗,配合实战案例多加练习,即可高效处理各类文本数据。

相关推荐
隐于花海,等待花开2 小时前
Hive专题:数据开发面试高频题(TopN、留存、连续登录等)
hive·hadoop·面试
木心术14 小时前
大数据处理技术:Hadoop与Spark核心原理解析
大数据·hadoop·分布式·spark
SelectDB技术团队18 小时前
基于 SelectDB 实现 Hive 数据湖统一分析:洋钱罐全球一体化探索分析平台升级实践
数据仓库·数据分析·apache doris·selectdb
爱喝水的鱼丶1 天前
SAP-ABAP:深入浅出 SAP AFVC 表:生产订单工序的核心数据仓库
运维·服务器·数据仓库·sap·abap·pp
KANGBboy1 天前
数仓数据治理
数据仓库
极光代码工作室1 天前
基于数据挖掘的高校图书借阅分析系统
大数据·hadoop·python·数据分析·数据可视化
zhixingheyi_tian1 天前
Hadoop 之 native 库
大数据·linux·hadoop·分布式
Hadoop_Liang1 天前
Hive的ORDER BY、SORT BY、DISTRIBUTE BY、CLUSTER BY对比及案例实践
数据仓库·hive·hadoop
杭州杭州杭州2 天前
数仓实验1
hive