Hive零基础从入门到实战 进阶篇(五) HiveQL:正则抽取、替换字符串函数

目录

 

前言

1. 正则表达式简介

1.1 定义

1.2 字符构成

1.3 速记指南

2. 正则抽取字符串函数 regexp_extract

3. 正则替换字符串函数 regexp_replace

4. 不同运行环境下的转义处理


 

前言

本文我们来详细介绍一下正则表达式,以及在Hive中通过正则匹配抽取、替换字符串的函数:

1. regexp_extract

2. regexp_replace

 

1. 正则表达式简介

这里依旧借用百度百科的讲解:

1.1 定义

正则表达式(Regular Expression,在代码中常Hive简写为regexp),又称规则表达式,是计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。

1.2 字符构成

正则表达式由一些普通字符和一些元字符组成。普通字符包括大小写的字母和数字,而元字符则具有特殊的含义,我们下面解释。在最简单的情况下,一个正则表达式看上去就是一个普通的查找串。例如,正则表达式"testing"中没有包含任何元字符,它可以匹配"testing"、"testing123"、"123testing"等任何包含"testing"的字符串,但是不能匹配"Testing"。

不过要想真正的用好正则表达式,最重要的是正确的使用各种元字符。下表列出了常用的元字符及对其简短的描述:

元字符

描述

\

转义字符。例如,“\n”代表换行符,如果想表示"\n"这个字符串,需要使用"\\n"来表示,也就是说"\\"代表字符"\"

^

匹配输入字行首。"^a"代表以a开头的任意字符串

$

匹配输入行尾。"a$"代表以a结尾的任意字符串

*

匹配前面的子表达式0次或多次。例如,zo*能匹配“z”,也能匹配“zo”以及“zoo”。*等价于{0,}。

+

匹配前面的子表达式一次或多次(大于等于1次)。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等价于{1,}。

?

匹配前面的子表达式零次或一次。例如,“do(es)?”可以匹配“do”或“does”。?等价于{0,1}。

{n}

n是一个非负整数。匹配确定的n次。例如,“o{2}”不能匹配到“Bob”中的“o”,但是能匹配“food”中的两个o。

{n,}

n是一个非负整数。至少匹配n次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等价于“o+”。“o{0,}”则等价于“o*”。

{n,m}

mn均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3}”将匹配“fooooood”中的前三个o为一组,后三个o为一组。“o{0,1}”等价于“o?”。请注意在逗号和两个数之间不能有空格。

?

当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少地匹配所搜索的字符串,而默认的贪婪模式则尽可能多地匹配所搜索的字符串。例如,对于字符串“oooo”,“o+”将尽可能多地匹配“o”,得到结果[“oooo”],而“o+?”将尽可能少地匹配“o”,得到结果 ['o', 'o', 'o', 'o']

.

匹配除“\n”和"\r"之外的任何单个字符。要匹配包括“\n”和"\r"在内的任何字符,请使用像“[\s\S]”的模式。

x|y

匹配x或y。例如,“z|food”能匹配“z”或“food”(此处请谨慎)。“[z|f]ood”则匹配“zood”或“food”。

[xyz]

字符集合。匹配所包含的任意一个字符。例如,“[abc]”可以匹配“plain”中的“a”。

[^xyz]

负值字符集合。匹配未包含的任意字符。例如,“[^abc]”可以匹配“plain”中的“plin”任一字符。

[a-z]

字符范围。匹配指定范围内的任意字符。例如,“[a-z]”可以匹配“a”到“z”范围内的任意小写字母字符。

注意:只有连字符在字符组内部时,并且出现在两个字符之间时,才能表示字符的范围; 如果出字符组的开头,则只能表示连字符本身.

[^a-z]

负值字符范围。匹配任何不在指定范围内的任意字符。例如,“[^a-z]”可以匹配任何不在“a”到“z”范围内的任意字符。

\d

匹配一个数字字符。等价于[0-9]。

\D

匹配一个非数字字符。等价于[^0-9]。

\n

匹配一个换行符。

\r

匹配一个回车符。

\s

匹配任何不可见字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。

\S

匹配任何可见字符。等价于[^ \f\n\r\t\v]。

\t

匹配一个制表符。

\v

匹配一个垂直制表符。

\w

匹配包括下划线的任何单词字符。类似但不等价于“[A-Za-z0-9_]”,这里的"单词"字符使用Unicode字符集。

\W

匹配任何非单词字符。等价于“[^A-Za-z0-9_]”。

( ) 将( 和 ) 之间的表达式定义为“组”(group),并且将匹配这个表达式的字符保存到一个临时区域(一个正则表达式中最多可以保存9个),它们可以用 \1 到\9 的符号来引用。

1.3 速记指南

.   [ ]  ^  $ 这四个字符是基础的正则表达式。正则难理解因为里面有一个等价的概念,这个概念大大增加了理解难度,让很多初学者看起来会懵,如果把等价都恢复成原始写法,自己书写正则就超级简单了,就像说话一样去写你的正则了:

等价:
等价是等同于的意思,表示同样的功能,用不同符号来书写。
?,*,+,\d,\w 都是等价字符
  ?等价于匹配长度{0,1}
  *等价于匹配长度{0,} 
  +等价于匹配长度{1,}
  \d等价于[0-9]
       \D等价于[^0-9]
  \w等价于[A-Za-z_0-9]
       \W等价于[^A-Za-z_0-9]


常用运算符与表达式:
  ^ 开始
  () 域段
  [] 包含,默认是一个字符长度
  [^] 不包含,默认是一个字符长度
  {n,m} 匹配长度 
  . 任何单个字符(\. 字符点)
  | 或
  \ 转义
  $ 结尾
  [A-Z] 26个大写字母
  [a-z] 26个小写字母
  [0-9] 0至9数字
       [A-Za-z0-9] 26个大写字母、26个小写字母和0至9数字
  , 分割
  分割语法:
  [A,H,T,W] 包含A或H或T或W字母
  [a,h,t,w] 包含a或h或t或w字母
  [0,3,6,8] 包含0或3或6或8数字

语法与释义:
  基础语法 "^([]{})([]{})([]{})$"
  正则字符串 = "开始([包含内容]{长度})([包含内容]{长度})([包含内容]{长度})结束" 
  
?,*,+,\d,\w 这些都是简写的,完全可以用[]和{}代替,初学者可以忽略?,*,+,\d,\w一些简写标示符,学会了基础使用再按表自己去等价替换。

  
实例:
  字符串:tel:086-0666-88810009999
  原始正则:"^tel:[0-9]{1,3}-[0][0-9]{2,3}-[0-9]{8,11}$" 
  速记理解:开始 "tel:普通文本"[0-9数字]{1至3位}"-普通文本"[0数字][0-9数字]{2至3位}"-普通文本"[0-9数字]{8至11位} 结束"
  等价简写后正则写法:"^tel:\d{1,3}-[0]\d{2,3}-\d{8,11}$" 

 

2. 正则抽取字符串函数 regexp_extract

regexp_extract(string subject, string pattern, int index)

功能:

将字符串subject按照pattern正则表达式的规则拆分,返回index指定的字符。注意,在有些情况下要使用转义字符。

第一参数 subject:   要处理的字段

第二参数 pattern:   用正则表达式匹配整个字段,然后用括号括出想要抽取的部分

w第三个参数 index:

  • 0是显示与之匹配的整个字符串
  • 1 是显示第一个括号里面的
  • 2 是显示第二个括号里面的字段,依此类推。

举例:

当第三个参数取0时,返回匹配到的整个字符串
hive (app)> select regexp_extract('wwwbaiducom','(www)(b.*)(com)',0);

wwwbaiducom

当第三个参数取1时,返回匹配到的字符串中第1个括号内所匹配的字符串
hive (app)> select regexp_extract('wwwbaiducom','(www)(b.*)(com)',1);

www

当第三个参数取2时,返回匹配到的字符串中第2个括号内所匹配的字符串
hive (app)> select regexp_extract('wwwbaiducom','(www)(b.*)(com)',2);

baidu

当第三个参数取3时,返回匹配到的字符串中第3个括号内所匹配的字符串
hive (app)> select regexp_extract('wwwbaiducom','(www)(b.*)(com)',3);

com

当第三个参数取4时,因为超出括号的对数3,所以报错
hive (app)> select regexp_extract('wwwbaiducom','(www)(b.*)(com)',4);
FAILED: SemanticException [Error 10014]: Line 1:7 Wrong arguments '4': org.apache.hadoop.hive.ql.metadata.HiveException: Unable to execute method public java.lang.String org.apache.hadoop.hive.ql.udf.UDFRegExpExtract.evaluate(java.lang.String,java.lang.String,java.lang.Integer)  on object org.apache.hadoop.hive.ql.udf.UDFRegExpExtract@267b678f of class org.apache.hadoop.hive.ql.udf.UDFRegExpExtract with arguments {wwwbaiducom:java.lang.String, (www)(b.*)(com):java.lang.String, 4:java.lang.Integer} of size 3

 

3. 正则替换字符串函数 regexp_replace

regexp_replace(string initial_string, string pattern, string replacement)

功能:

将字符串initial_string中的符合正则表达式pattern的部分替换为replacement。注意,在有些情况下要使用转义字符。

第一参数 initial_string:   要处理的字段

第二参数 pattern:   正则表达式匹配字段中想要替换的部分

第三个参数 replacement:替换成的字符串

举例:

将字符串中的baidu替换为.google.
hive (app)> select regexp_replace('wwwbaiducom','baidu','.google.');

www.google.com

 

4. 不同运行环境下的转义处理

有时正则匹配需要对一些特殊字符进行转义处理,比如 . 在正则表达式中表示一个任意字符,如果想在正则表达式中表示.这个字符串,就需要使用\进行转义,但是!

在Hive的CLI环境下,\也需要进行转义,所以表示一个.的正确写法是 \\.

举例:

需求:把www.baidu.com中的.替换成-

如果直接使用.,会将所有字符替换成-,因为.代表任意一个字符
hive (app)> select regexp_replace('www.baidu.com','.','-');

-------------

如果转义使用\.,仍然会将所有字符替换成-,因为\也需要转义
hive (app)> select regexp_replace('www.baidu.com','\.','-');

-------------

转义使用\\.,成功替换
hive (app)> select regexp_replace('www.baidu.com','\\.','-');
OK
_c0
www-baidu-com

在hive -e和hive -f的执行环境下,转义需要四个\,即\\\\.代表字符串.

举例:

使用\\.会转义失败,仍然将所有字符替换为-
[root@hadoop ~]# hive -e "select regexp_replace('www.baidu.com','\\.','-');"

-------------

使用\\\\.转义成功,将.正常替换为-
[root@hadoop ~]# hive -e "select regexp_replace('www.baidu.com','\\\\.','-');"

www-baidu-com

hive -f同理,需要使用\\\\.才能转义成功
[root@hadoop ~]# vim regexp.hql
vim 写入select regexp_replace('www.baidu.com','\\\\.','-');
[root@hadoop ~]# hive -f regexp.hql 

www.baidu.com

 


能看到这里的同学,就右上角点个赞吧,3Q~

你可能感兴趣的:(Hive零基础从入门到实战 进阶篇(五) HiveQL:正则抽取、替换字符串函数)