在之前文章中(文章如下),小白有讲过正则的三个函数,替换、截取等操作。在工作中,又遇到了其他的问题,这里做一个进阶的讲解文章,欢迎遇到类似问题的小伙伴一起学习交流。

初级用法参照下面的文章

Hive SQL 正则表达式进阶一(regexp的三个函数)https://blog.csdn.net/Jarry_cm/article/details/87272189

场景一

有以下几种情况的数据,需要将15|后面的内容取出来,后面有可能是英文,有可能是数字,位置不固定。

我们看下几种SQL的形式:

第一种:

select regexp_extract('15|Range,16|5,31|369728,17|1',"(15\\|)(.*?)(,)",2) as r1,
       regexp_extract('16|5,15|30,31|369728,17|1',"(15\\|)(.*?)(,)",2) as r2,
       regexp_extract('16|5,31|369728,17|1,15|Range',"(15\\|)(.*?)(,)",2) as r3,
       regexp_extract('15|30',"(15\\|)(.*?)(,)",2) as r4

结果如下:前两种能解析出来,后两种解析不出

这是因为,后面两种没有逗号,所以是不匹配的

r1r2r3r4
Range30 

那有人会说,我把逗号去掉,数字变为1不就好了么,OK来试一下

第二种:这里需要注意一下  .*?  表示匹配任意字符到下一个符合条件的字符,这里把后面的逗号去掉了,那就从来都不会满足该条件,因此,无论哪种形式,第二个位置都不会匹配出来

看一下填1

select regexp_extract('15|Range,16|5,31|369728,17|1',"(15\\|)(.*?)",1) as r1,
       regexp_extract('16|5,15|30,31|369728,17|1',"(15\\|)(.*?)",1) as r2,
       regexp_extract('16|5,31|369728,17|1,15|Range',"(15\\|)(.*?)",1) as r3,
       regexp_extract('15|30',"(15\\|)(.*?)",1) as r4

结果:

r1r2r3r4
15|15|15|15|

 看一下填2

select regexp_extract('15|Range,16|5,31|369728,17|1',"(15\\|)(.*?)",2) as r1,
       regexp_extract('16|5,15|30,31|369728,17|1',"(15\\|)(.*?)",2) as r2,
       regexp_extract('16|5,31|369728,17|1,15|Range',"(15\\|)(.*?)",2) as r3,
       regexp_extract('15|30',"(15\\|)(.*?)",2) as r4

结果:

r1r2r3r4
   

看一下填0,0是符合所有条件的结果,第二个永远遍历不完,所以结果和填1是一样的

select regexp_extract('15|Range,16|5,31|369728,17|1',"(15\\|)(.*?)",0) as r1,
       regexp_extract('16|5,15|30,31|369728,17|1',"(15\\|)(.*?)",0) as r2,
       regexp_extract('16|5,31|369728,17|1,15|Range',"(15\\|)(.*?)",0) as r3,
       regexp_extract('15|30',"(15\\|)(.*?)",0) as r4

结果:

r1r2r3r4
15|15|15|

15|

 

 因此,这里们要分析,竖线后面有哪些形式,英文或者是数字,那么第二个匹配我们应该匹配英文或数据,那下面写法就可以达到目的了。

select regexp_extract('15|Range,16|5,31|369728,17|1',"15\\|(([A-Za-z]{1,})|(\\d{1,}))",1) as r1,
       regexp_extract('16|5,15|30,31|369728,17|1',"15\\|(([A-Za-z]{1,})|(\\d{1,}))",1) as r2,
       regexp_extract('16|5,31|369728,17|1,15|Range',"15\\|(([A-Za-z]{1,})|(\\d{1,}))",1) as r3,
       regexp_extract('15|30',"15\\|(([A-Za-z]{1,})|(\\d{1,}))",1) as r4,
       regexp_extract('15|Range',"15\\|(([A-Za-z]{1,})|(\\d{1,}))",1) as r5,
       regexp_extract('16|5,15|Range,31|369728,17|1',"15\\|(([A-Za-z]{1,})|(\\d{1,}))",1) as r6
       

总的来说,正则中有很多小知识点,做正则时除了需要细心,掌握每种可能的情况,才能正确的解析。

更多推荐