最近有个需求,需要在hive数据仓库中筛选一批较为规整的数据, 并将其中特定字符截取出来,并统计分析。
过程中用到了正则匹配的函数 regexp_extract,现简单记录下,方便以后使用时查阅。
内容大纲
1 regexp_extract 函数语法
2.1 基础语法
语法: regexp_extract(string A, string pattern, int index)
返回值: string
说明:将字符串A按照正则表达式的规则拆分,返回index指定的部分(从1开始,0表示输出所有已匹配值)
简而言之,index为0时会返回所有匹配,index为其他值n时,只返回第n段匹配
举例:
regexp_extract('【e往无前】亚索您好,电刀正申请退货,验证码666666','[0-9]{6}',0)
此时返回值为 正则匹配到的 666666
regexp_extract('【e往无前】亚索您好,电刀正申请退货,验证码666666','(^【.*】).*[0-9]{6}',0)
2.2 正则贪婪模式的影响
regexp_extract('【e往无前】亚索您已掉线333天,封号666天','(^【.*】).*([0-9]{3})',2)
此时返回值为 第2个括号括起来的匹配,即([0-9]{3}) 匹配到的 666
额外说明: 返回值之所以不是前边的333 , 是因为在贪婪(默认)模式下,正则引擎会尽可能匹配更长的字符,若在.*后加上?则可关闭贪婪模式,开启懒惰模式。此时正则引擎会 尝试尽可能匹配更多次字符
regexp_extract('【e往无前】亚索您已掉线333天,封号666天','(^【.*】).*?([0-9]{3})',2)
此时返回值为 第2个括号括起来的匹配,即([0-9]{3}) 匹配到的 333
regexp_extract('【e往无前】亚索您已掉线333天,封号666天','(^【.*】).*?([0-9]{3})',0)
此时由于最后指定了0,即输出所有匹配,所以最后返回值为 【e往无前】亚索您已掉线333
2 测试数据构建
以上例子基本可以说明此函数的用法
为了进行更多演示,我在hive中创建了一个测试表,并构建了一些数据。
# 创建一个新的测试表,表中只有2个字段:电话号码 和 短信内容
hive -e"
CREATE TABLE test_aaa (
dest_number string,
content string
)
stored as orc"
构建一些数据并导入
hive -e"
INSERT INTO test_aaa (dest_number,content) VALUES
('17300001111','【草结笔记】您好,您的验证码是666666,退订回T'),
('17300001111','【e往无前】亚索您好,您的验证码是666666,退订回T'),
('17300001111','【小蘑菇】提莫您好,您今日复活次数为222333,下次活得久一点哦~'),
('15600001111','【我从不妥协】男刀锋您好,您的验证码:456144,感谢购买我店的拖鞋,路途愉快'),
('15600001111','【飞天锡纸螂】卡兹克您好,感谢购买星噬,您的验证码:666666,别给其他人看哦,退订回T'),
('15600001111','【e往无前】亚索您好,您的电刀正申请退货,验证码是666666'),
('13600001111','【大大太阳】您的验证码为123456,欢迎光临~'),
('18700001111','【大郎足浴城】欢迎注册会员,您的验证码是222333'),
('18700001111','【大郎足浴城】您好,本次您共消费222333元,期待下次光临~'),
('17300001111','【e往无前】亚索您好,验证码是666666,别再浪了')"
3 更多具体实例演示
1) 基于 号码、签名、验证码 分组
hive -e "
select
dest_number,
regexp_extract(content,'(^【.*】).*([0-9]{6})',1),
regexp_extract(content,'(^【.*】).*([0-9]{6})',2),
count(1) as total
from test_aaa
where content like '%验证码%'
group by dest_number,
regexp_extract(content,'(^【.*】).*([0-9]{6})',1),
regexp_extract(content,'(^【.*】).*([0-9]{6})',2)
order by total desc
"
2)根据号码、可能的人名(称谓)分组
hive -e " select
dest_number,
regexp_extract(content,'^【.*】(.*)您好',1),
count(1) as total
from test_aaa
where content like '%您好%'
group by dest_number,
regexp_extract(content,'^【.*】(.*)您好',1)
order by total desc "
3)根据号码、验证码分组
hive -e " select
dest_number,
regexp_extract(content,'^【.*】.*([0-9]{6})',1),
count(1) as total
from test_aaa
where content like '%验证码%'
group by dest_number,
regexp_extract(content,'^【.*】.*([0-9]{6})',1)
order by total desc "