【hive】从url中提取需要的部分字符串

本人菜鸟一只,如果有什么说错的地方还请大家批评指出!!

事情是这样的,hive的A表中,有url这样的一个字段,我想要提取这个字段中的某一部分(这不就是截取字符串嘛)。但是substring肯定是满足不了我的需求的,自己写hive的udf也不太现实(用最简单的方式完成任务,才会让后来的维护变得更加方便,否则除了维护sql还要维护一堆udf,那才叫可怕)。因此我初步的想法就是正则!然后经过同事的提醒,我知道了hive有自带函数可以处理url,所以我来总结下三种方案! 

url格式是这样的(我想要获取group_id=后面的数字): 

/wenzhang/v1/XXX/?fold=1&offset=0&group_id=6594293942836003076&tab_index=0&count=20&(后面还有一大堆杂七杂八的东西)

方法一:通过正则获得字符串(hive处理正则的函数regexp_extract)

先说一句hive自带函数的官方网站:https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF

正则中有个叫零宽断言的东西,大概说的就是取某个字符串的前面的字符,或者取后面的字符

题外话:

有个我觉得不错的学习归纳正则网站:https://www.jb51.net/tools/zhengze.html

然后大家可以去这个页面上试试正则:http://tool.chinaz.com/regex/

有一点提醒下大家,每个框架(不同开发语言,不同数据库)支持的正则并不是完全一样的,所以测试非常重要,不要拿了别人写的东西就直接用,有很大几率是不成功的!

推荐一款工具:RegexBuddy(图表是一个猫头鹰),用来测试不同环境下的正则的~

言归正传:

所以我写出的正则规则是这样:(?<=group_id=)\d{1,}

意思就是匹配group_id=这串字符串后面的1到无穷多个数字(实际测试可行)

那么hive中,应该如何来写这个正则呢?

其实又有点不一样,如下图:

select split(regexp_extract(split(url,'/')[4],'group_id=([0-9]+)',0),'=')[1] from 数据库.表A  limit 1;

官网的解释如下,如果对于传入什么参数还不太明白的话,可以百度中文博客,或者去看hive源码,看这个方法到底如何通过java代码来处理传入的参数!(这里不多加赘述,因为很好百度到)

方法二:自己写自定义函数来解析(本人最不推荐的方法)

hive官网关于如何添加自定义函数:https://cwiki.apache.org/confluence/display/Hive/HivePlugins

具体如何操作可以看官网或者百度中文的帖子或者给我留言,我就不写明,在这里就单纯做个简单的阐述。

1、添加临时函数,只有当前hive的连接有效(当然对于以后一直需要使用的自定义函数,使用这个明显不合理)

2、添加非临时函数(做法其实是将函数打成jar包,上传到hdfs,让每个hive客户端连接的时候,加载这个jar包,但是大家不觉得多维护一个jar包是一件很麻烦的事情吗?)

实在是不推荐这种方式,不到万不得已千万不要想着自己添加这添加那的,可能这个东西你自己维护,你没觉得什么,当下一个人维护你的程序的时候,就该骂人了!

方法三:使用hive自带的解析url的函数(parse_url)

说实话,这也是一搜一大把的函数

并且官方也写了例子出来,挺简单的。但是这个函数还是有要求的,他要求url必须工整。

例如:我的表中的url格式如下

/wenzhang/v1/XXX/?fold=1&offset=0&group_id=6594293942836003076&tab_index=0&count=20&(后面还有一大堆杂七杂八的东西)

也就是说他没有http://这个头,对不起,这个函数解析不了,因此就必须把每个url加上一个http头!

注意:不同数据库的字符串拼接会有些许差异,有的直接用"+",有的用"||"(greenplum),hive中使用"concat"这个函数

因此有缺陷的sql如下:

--第二个位置上的参数可以传入:HOST, PATH, QUERY, REF, PROTOCOL, AUTHORITY, FILE, and USERINFO来获取url的不同部分 
select parse_url(concat('http://',url), 'QUERY','group_id') from 数据库.表A

一定要特别注意:

因为如果数据原来有https://的头,然后你强行加了http://头,这样url_host解析出来就是https!!

所以正确的sql如下:

--第二个位置上的参数可以传入:HOST, PATH, QUERY, REF, PROTOCOL, AUTHORITY, FILE, and USERINFO来获取url的不同部分 
select parse_url(case when url like 'http://%' or url like 'https://%' then url else concat('http://',url) end,'HOST') as url_host from 数据库.表A

我觉得这篇文章写的还可以大家也可直接参考:https://www.cnblogs.com/itdyb/p/6236953.html(作者:波比12)

 

ok,所以我最后采用的是方法三,看起来性能也还行(当然我也没有做具体的测试,我没有选择方法一的原因是,我担心正则有时候可能会有些效率问题,就是慢),如果有各位大神实际测试过这两种方法的速度,可以给我留言,让我也记录学习下,谢谢~

老话说一下,本人菜鸟一只,如果有什么说错的地方还请大家批评指出!!我一定虚心学习!

  • 9
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值