Hive之正则表达式

Hive版本:hive-3.1.2

目录

一、Hive的正则表达式概述

[1.1 字符集合](#1.1 字符集合)

[1.2 边界集合](#1.2 边界集合)

[1.3 量词(重复次数)集合](#1.3 量词(重复次数)集合)

[1.4 转义操作符](#1.4 转义操作符)

[1.5 运算符优先级](#1.5 运算符优先级)

[二、Hive 正则表达式案例](#二、Hive 正则表达式案例)

[2.1 like](#2.1 like)

[2.2 rlike](#2.2 rlike)

[2.3 regexp](#2.3 regexp)

[2.4 regexp_replace正则替换](#2.4 regexp_replace正则替换)

[2.5 regexp_extract正则提取](#2.5 regexp_extract正则提取)

2.6、hive实现Oracle中的REGEXP_SUBSTR

三、完整代码示例

场景:清洗日志数据

四、注意事项

五、常用正则模式

六、工作中高频使用

1、数据清洗(脱敏、格式转换)

2、日志解析(提取关键信息)

3、URL参数解析(电商/广告分析)

4、电话号码格式校验(金融/电信)

七、Hive正则核心函数强化

[1、REGEXP_EXTRACT 动态提取](#1、REGEXP_EXTRACT 动态提取)

[2、REGEXP_REPLACE 复杂替换](#2、REGEXP_REPLACE 复杂替换)

[3、RLIKE 多条件过滤](#3、RLIKE 多条件过滤)

一、Hive的正则表达式概述

正则表达式是一种用于匹配和操作文本的强大工具,它是由一系列字符和特殊字符组成的模式,用于描述要匹配的文本模式。Hive 支持基于正则表达式的字符串处理,常用于数据清洗、模式匹配和文本提取 ,本篇文章主要对hive正则表达式的总结归纳。

Hive支持如下正则表达式:

  • like
  • rlike
  • regexp
  • regexp_extract
  • regexp_replace

1.1 字符集合

|---------------|------------------------------------------------------------------|
| 字符 | 描述 |
| [a-z] | 字符范围。匹配指定范围内的任意字符。例如,'[a-z]' 可以匹配 'a' 到 'z' 范围内的任意小写字母字符。 |
| [A-Z] | '[A-Z]' 可以匹配 'A' 到 'Z' 范围内的任意大写字母字符。 |
| [^a-z] | 匹配任何不在指定范围内的任意字符。例如,'[^a-z]' 可以匹配任何不在 'a' 到 'z' 范围内的任意字符。 |
| \d | 匹配一个数字字符,等价于[0-9],匹配所有的数字 |
| \D | 匹配一个非数字字符,等价于[^0-9] |
| \w | 匹配字母、数字、下划线。等价于'[A-Za-z0-9_]' |
| \W | 匹配非字母、数字、下划线。等价于 '[^A-Za-z0-9_]' |
| \s | 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v] |
| \S | 匹配任何非空白字符。等价于 [^ \f\n\r\t\v] |
| \f | 匹配一个换页符。 |
| \n | 匹配一个换行符。等价于 \x0a 和 \cJ |
| \r | 匹配一个回车符。等价于 \x0d 和 \cM |

1.2 边界集合

|--------|-----------------------|
| 字符 | 描述 |
| ^ | 每一行的开头,单行模式下等价于字符串的开头 |
| $ | 每一行的结尾,单行模式下等价于字符串的结尾 |

1.3 量词(重复次数)集合

|-----------|-------------------------------------------------------------------------------|
| 字符 | 描述 |
| * | 匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,} |
| + | 匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,} |
| ? | 匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 。? 等价于 {0,1} |
| {n} | n 是一个非负整数。匹配确定的 n 次。例如,'o{2}'能匹配 "food" 中的两个 o |
| {n,} | n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 能匹配 "foooood" 中的所有 o |
| {n,m} | m 和n均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 将匹配 "fooooood" 中的前三个 o |

1.4 转义操作符

|--------|--------------------------------------------------------|
| 字符 | 描述 |
| \ | 将下一个字符标记为一个特殊字符、或一个原义字符等。例如,'n' 匹配字符 "n"。'\n' 匹配一个换行符 |

1.5 运算符优先级

正则表达式从左到右进行计算,并遵循优先级顺序。相同优先级的从左到右进行运算,不同优先级的运算先高后低。下表从最高到最低说明了各种正则表达式运算符的优先级顺序:

|-------------------------------|---------------------------------|-------------------------------|
| 运算符 | 描述 | 示例 |
| 转义符\ | \ 是用于转义其他特殊字符的转义符号。它具有最高的优先级。 | \d 匹配数字,\. 匹配点号 |
| 圆括号() | 圆括号()用于创建子表达式,具有高于其他运算符的优先级。 | (abc)+ 匹配 "abc" 一次或多次 |
| 量词 *, +, ?, {n}, {n,}, {n,m} | 量词指定前面的元素可以重复的次数。 | a* 匹配零个或多个 "a" |
| 定位点^, | `^` 表示行的开头,`表示行的结尾 | | | 管道符号\| ||表示"或"关系,用于在多个模式之间选择一个 |cat|dog` 能够匹配到 "cat" 或 "dog" |

复制代码
举例:\d{2,3}|[a-z]+(abc)* 的运算顺序
  • \d{2,3} 匹配两到三个数字
  • | 表示或
  • [a-z]+ 匹配一个或多个小写字母
  • (abc)* 匹配零个或多个 "abc"

二、Hive 正则表达式案例

2.1 like

  • 语法1: A like B
  • 语法2: like(A, B)
  • 操作类型: strings
  • 返回类型:boolean或null
  • 描述:如果字符串A或者字符串B为null,则返回null;如果字符串A符合表达式B 的正则语法,则为true;否则为false。B中字符"_"表示任意单个字符 ,而字符"%"表示任意数量的字符
sql 复制代码
-- 举例:

select 'ahngnfg' like '%nfg'  --> true (%nfg也可以理解为以'nfg'结尾的字符)

select 'ahngnfg' like 'nfg%'  --> false(nfg%也可以理解为以'nfg'开头的字符)

select 'ahngnfg' like '%nfg%'  --> true (%nfg% 也可以理解为包含'nfg'的字符)

2.2 rlike

  • 语法1: A rlike B
  • 语法2: rlike (A, B)
  • 操作类型: strings
  • 返回类型: boolean或null
  • 描述: 如果字符串A或者字符串B为null,则返回null;如果字符串A符合JAVA正则表达式 B的正则语法,则为true;否则为false。B中字符"_"表示任意单个字符 ,而字符"%"表示任意数量的字符

java正则:

"." 任意单个字符

"*" 匹配前面的字符0次或多次

"+" 匹配前面的字符1次或多次

"?" 匹配前面的字符0次或1次

"\d" 匹配一个数字字符,等于[0-9],使用的时候写成'\\d'

"\D" 匹配一个非数字字符,等于[^0-9],使用的时候写成'\\D'

sql 复制代码
-- 举例:
select '2314' rlike '\\d+';  --> true
select 'numrqe' rlike '^num'; --> true

2.3 regexp

  • 语法1: A regexp B
  • 语法2: regexp (A, B)
  • 操作类型: strings
  • 返回类型: boolean或null
  • 描述: 功能与rlike相同
sql 复制代码
with tmp1 as
(
select '12325abc' as rn
union all
select 'b91256ab56' as rn
union all
select 'bfs89abc21' as rn
)
select rn
  from tmp1
 where rn regexp '\\d{5}';
sql 复制代码
-- 匹配开头有3个及以上连续数字的字符
with tmp1 as
(
select '12325abc' as rn
union all
select '91fe56' as rn
union all
select 'bfs89abc21' as rn
)
select rn
  from tmp1
 where rn regexp '^\\d{3}';
sql 复制代码
-- 匹配开头只有3个连续数字的字符
with tmp1 as
(
select '12325abc' as rn
union all
select '912fe56' as rn
union all
select 'bfs89abc21' as rn
)
select rn
  from tmp1
 where rn regexp '^\\d{3}\\D';

2.4 regexp_replace正则替换

判断字符串是否匹配正则表达式模式(返回布尔值)

REGEXP_REPLACE(string, pattern, replacement)

replacement:替换后的字符串,可使用 $n 引用捕获组

sql 复制代码
-- 举例:

select regexp_replace('h234ney', '\\d+', 'fd'); --> hfdney

-- 隐藏手机号中间4位
SELECT REGEXP_REPLACE('电话: 13812345678', '(\\d{3})\\d{4}(\\d{4})', '$1****$2');
-- 输出: 电话: 138****5678

2.5 regexp_extract正则提取

从字符串中提取符合正则表达式模式的子字符串。

REGEXP_EXTRACT(string, pattern, index)

  • string:原始字符串

  • pattern:正则表达式模式

  • index:捕获组的索引(从 1 开始)

sql 复制代码
-- 提取手机号中的前3位(运营商号段)
SELECT REGEXP_EXTRACT('用户电话: 13812345678', '(\\d{3})\\d{8}', 1); 
-- 输出: 138

select regexp_extract('honeymoon', 'hon(.*?)(oon)', 0); --> honeymoon
select regexp_extract('honeymoon', 'hon(.*?)(oon)', 1); --> eym
select regexp_extract('honeymoon', 'hon(.*?)(oon)', 2); --> oon

2.6、hive实现Oracle中的REGEXP_SUBSTR

oracle:

sql 复制代码
SELECT REGEXP_SUBSTR('订单时间:2023-10-05 12:30', '\d{4}-\d{2}-\d{2}') FROM dual

首先需要清楚regexp_substr()的作用,先看官方解释REGEXP_SUBSTR通过允许您在字符串中搜索正则表达式模式来扩展功能的功能。它也与相似REGEXP_INSTR,但是它不返回子字符串的位置,而是返回子字符串本身。如果您需要匹配字符串的内容,而不是它在源字符串中的位置,则此功能很有用。该函数返回的字符串形式为VARCHAR2或,并且CLOB数据的字符集与相同source_char。

接下来对函数中的各个参数进行说明:

sql 复制代码
REGEXP_SUBSTR(source_char, pattern, position, occurrence, match_parameter)

1、source_char:通常是用作正则处理的字符串

2、pattern:[正则表达式](https://www.runoob.com/regexp/regexp-tutorial.html)

3、position:正整数,指示source_char应该在哪里开始搜索的字符。默认值为1,表示从第一个字符开始搜索source_char。

4、occurrence:获取第几个分割出来的组。默认值为1,表示Oracle搜索的第一个匹配项pattern。

5、match_parameter:模式('i'不区分大小写进行检索;'c'区分大小写进行检索。默认为'c')针对的是正则表达式里字符大小写的匹配

再来看hive中regexp_extract()函数描述:

sql 复制代码
regexp_extract(str, regexp[, idx]) 

参数解释:

其中:
1、str是被解析的字符串

2、regexp 是正则表达式

2.1、idx是返回结果 取表达式的哪一部分 默认值为1。

2.2、0表示把整个正则表达式对应的结果全部返回

2.3、1表示返回正则表达式中第一个() 对应的结果 以此类推

注意点:

要注意的是idx的数字不能大于表达式中()的个数。否则报错。

通过对比oracle中的REGEXP_SUBSTR()函数不难看出,再对regexp_extract()的结果进行截取即可。

例如:

sql 复制代码
--oracle中的语句是:
select REGEXP_SUBSTR('cvdfer--gth--mn','[^--]+',1,2) from dual;

--hive改写后:
select nvl(split('cvdfer--gth--mn','--')[1],'cvdfer--gth--mn');

--提取第一个匹配的字符串
oracle中:select REGEXP_SUBSTR('cvdfer--gth--mn','[^--]+',1,1) from dual;
select regexp_extract('cvdfer--gth--mn','[^--]+',0);


--oralce:
SELECT REGEXP_SUBSTR('订单时间:2023-10-05 12:30', '\d{4}-\d{2}-\d{2}') FROM dual

--hive改写后:
SELECT split((split('订单时间:2023-10-05 12:30',':')[1]),' ')[0];
select regexp_extract('订单时间:2023-10-05 12:30','\\d{4}-\\d{2}-\\d{2}',0);

三、完整代码示例

场景:清洗日志数据

sql 复制代码
-- 创建示例表
CREATE TABLE server_logs (
  log_id INT,
  log_message STRING
);

-- 插入数据
INSERT INTO server_logs VALUES
(1, 'Error: Disk full on /dev/sda1 (IP: 192.168.1.10)'),
(2, 'User login: alice@example.com from 10.0.0.5'),
(3, 'WARN: Memory usage 90% (host: server-01)');

-- 提取所有IP地址
SELECT 
  log_id,
  REGEXP_EXTRACT(log_message, '(\\d+\\.\\d+\\.\\d+\\.\\d+)', 1) AS ip_address
FROM server_logs
WHERE log_message RLIKE '\\d+\\.\\d+\\.\\d+\\.\\d+';

-- 结果:
-- log_id | ip_address
-- 1      | 192.168.1.10
-- 2      | 10.0.0.5

四、注意事项

  1. 转义字符 :Hive 使用 Java 正则语法,需对反斜杠 \ 双重转义(如 \\d 匹配数字)。

  2. 性能:复杂正则可能影响查询效率,建议预处理数据。

  3. 模式贪婪性 :默认贪婪匹配,使用 ? 启用非贪婪模式(如 .*?)。

  4. 捕获组 :使用 () 定义捕获组,通过索引引用(如 $1)。

五、常用正则模式

场景 正则表达式
邮箱 [A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}
IPv4 地址 \\d+\\.\\d+\\.\\d+\\.\\d+
URL https?://[^\\s]+
日期(YYYY-MM-DD) \\d{4}-\\d{2}-\\d{2}

六、工作中高频使用

1、数据清洗(脱敏、格式转换)

需求:隐藏用户手机号中间4位,并提取邮箱用户名。

sql 复制代码
-- 示例数据:user_info表字段 user_contact = '13812345678,alice@example.com'
SELECT 
  REGEXP_REPLACE(regexp_extract('13812345678,alice@example.com', '^\\d+', 0), '(\\d{3})\\d{4}(\\d{4})', '$1****$2') AS phone_mask,  -- 脱敏手机号
  REGEXP_EXTRACT('13812345678,alice@example.com', '([A-Za-z0-9._%+-]+)@', 1) AS email_user            -- 提取邮箱用户名

-- 结果:
-- phone_mask      | email_user
-- 138****5678     | alice

2、日志解析(提取关键信息)

需求:从服务器日志中提取IP、时间戳和错误级别。

sql 复制代码
-- 示例日志:'2023-10-05 14:30:22 [ERROR] Failed to connect from 192.168.1.105'
SELECT 
  REGEXP_EXTRACT(log_line, '(\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2})', 1) AS log_time,
  REGEXP_EXTRACT(log_line, '\\[(WARN|ERROR|INFO)\\]', 1) AS log_level,
  REGEXP_EXTRACT(log_line, '(\\d+\\.\\d+\\.\\d+\\.\\d+)', 1) AS client_ip
FROM server_logs
WHERE log_line RLIKE '\\[(WARN|ERROR|INFO)\\]';  -- 过滤包含日志级别的行

3、URL参数解析(电商/广告分析)

需求:从URL中提取商品ID或广告渠道参数。

sql 复制代码
-- 示例URL:'https://shop.com/product?id=12345&source=wechat'
with user_clicks as (
select 
 'https://shop.com/product?id=12345&source=wechat' url
)
SELECT 
  REGEXP_EXTRACT(url, 'id=(\\d+)', 1) AS product_id,           -- 提取id参数
  REGEXP_EXTRACT(url, 'source=([a-zA-Z]+)', 1) AS ad_source     -- 提取source参数
FROM user_clicks;

4、电话号码格式校验(金融/电信)

需求:校验手机号是否为合法中国11位号码。

sql 复制代码
-- 匹配规则:以13/14/15/17/18/19开头的11位数字
with customer_contacts as (
select '13812345678' phone_number
union all
select '123456' phone_number
)
SELECT 
  phone_number,
  CASE WHEN phone_number RLIKE '^1[3-9]\\d{9}$' THEN 'Valid' ELSE 'Invalid' END AS check_result
FROM customer_contacts;

七、Hive正则核心函数强化

1、REGEXP_EXTRACT 动态提取

sql 复制代码
-- 提取JSON字符串中的指定字段(非标准JSON场景)
-- 示例数据:'{"order_id": "A1001", "amount": 299.5}'
with order_logs as (
select '{"order_id": "A1001", "amount": 299.5}' json_str
)
SELECT 
  REGEXP_EXTRACT(json_str, '"order_id":\\s*"([^"]+)"', 1) AS order_id,  -- 提取A1001
  REGEXP_EXTRACT(json_str, '"amount":\\s*(\\d+\\.?\\d*)', 1) AS amount  -- 提取299.5
FROM order_logs;

2、REGEXP_REPLACE 复杂替换

sql 复制代码
-- 清理文本中的乱码(如替换非数字、字母、中文以外的字符)
with unstructured_data as (
select '用户#@!名:张三_2023' raw_text
)
SELECT 
  REGEXP_REPLACE(raw_text, '[^\\u4e00-\\u9fa5a-zA-Z0-9]', '') AS cleaned_text 
FROM unstructured_data;

-- 输入:'用户#@!名:张三_2023' → 输出: '用户名张三2023'

3、RLIKE 多条件过滤

sql 复制代码
-- 筛选包含"支付成功"或"订单完成"的日志(金融风控)
SELECT *
FROM transaction_logs
WHERE log_message RLIKE '支付成功|订单完成';

参考文章

(06)Hive------正则表达式_hive正则表达式-CSDN博客

相关推荐
周杰伦fans1 天前
C# 正则表达式完全指南
mysql·正则表达式·c#
8***a8151 天前
从0到1部署Tomcat和添加servlet(IDEA2024最新版详细教程)
hive·servlet·tomcat
5***79003 天前
JavaScript生成器函数
hive·tidb·consul
顧棟3 天前
HDFS元数据与auditlog结合Hive元数据统计分析
hive·hadoop·hdfs
yumgpkpm3 天前
腾讯云TBDS与CDH迁移常见问题有哪些?建议由CDH迁移到CMP 7.13 平台(类Cloudera CDP,如华为鲲鹏 ARM 版)
hive·hadoop·zookeeper·flink·spark·kafka·hbase
梦里不知身是客114 天前
正则表达式常见的介绍
前端·javascript·正则表达式
狮智先生4 天前
【编程实践】正则表达式的使用
正则表达式
yumgpkpm4 天前
数据可视化AI、BI工具,开源适配 Cloudera CMP 7.3(或类 CDP 的 CMP 7.13 平台,如华为鲲鹏 ARM 版)值得推荐?
人工智能·hive·hadoop·信息可视化·kafka·开源·hbase
二进制_博客5 天前
使用datax将mysql数据抽取到hive分区表无数据
数据库·hive·mysql
干就完事了5 天前
Hive视图
数据仓库·hive·hadoop