• hive 中正则表表达式使用


     一 概念

    概念:正则表达式(Regular Expression),又称规则表达式,是记录文本规则的代码。通常被用来检索、替换那些符合某个模式(规则)的文本。

    特性:最初是由Unix中的工具软件(例如sed和grep)普及开的,现在许多程序设计语言都支持利用正则表达式。

    常见缩写:正则表达式在代码中,通常缩写成regex、regexp、RE,复数有regexps、regexes、regexen等。

    二、语法

    1、正则表达式保留字符

    代码

    说明

    [ ] \ ^ $ . | ? * + ( ) { }

    正则保留字,如果想匹配为文本字符时,需要使用“\”进行转义

    | 代表或,也成为分支条件,例:x|y 匹配x或者y

    [ ] 用于定义字符集,例:[aeiou] 匹配英文元音字母

    ( ) 用于形成组,后续会讲到

    { } 用于定义重复操作,后续会讲到

    示例\. 匹配字符“.”

    \\ 匹配字符“\”

    2、非打印字符

    除了匹配字符串之外,正则表达式还可以匹配非打印字符:

    代码

    说明

    \cx

    匹配由x指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符

    \f

    匹配一个换页符。等价于 \x0c(十六进制) 和 \cL(控制字符

    \n

    匹配一个换行符。等价于 \x0a 和 \cJ

    \r

    匹配一个回车符。等价于 \x0d 和 \cM

    \t

    匹配一个制表符。等价于 \x09 和 \cI

    \v

    匹配一个垂直制表符。等价于 \x0b 和 \cK

    \s

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

    \S

    匹配任何非空白字符。等价于 [^ \f\n\r\t\v]

    3、字符集

    代码

    说明

    备注

    \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]

    .

    匹配除换行符以外的任意字符。等价于[^\n\r]

    4、边界符

    代码

    说明

    ^

    匹配字符串的开始

    $

    匹配字符串的结束

    \b

    匹配单词的开始或结束

    \B

    匹配不是单词开头或结束的位置

    5、量词、重复

    代码/语法

    说明

    *

    重复零次或更多次

    +

    重复一次或更多次

    ?

    重复零次或一次

    {n}

    重复n次

    {n,}

    重复n次或更多次

    {n,m}

    重复n到m次

    \ba\w*\b  匹配以字母a开头的单词

    Windows\d+ 匹配Windows后面跟1个或更多数

    \b\w{6}\b 匹配刚好6个字符的单词

    注意:量词本身是贪婪匹配,即返回最长的匹配;量词后加 ? 可以实现非贪婪或最小匹配

    例如,对字符串“Windows98” 使用下面不同的正则表达式,结果不同:

    表达式:Windows\d+ 匹配结果为: Windows98 说明:\d+ 按最长的数字匹配

    表达式:Windows\d+? 匹配结果为: Windows9 说明:\d+? 按最短的数据匹配

    举个实际的数据清洗例子,对字符串“orderid:12344,create_time:2020-10-10 00:00:00, ” 中的进行匹配:

    表达式:orderid:(.*), 匹配结果为: 12344,create_time:2020-10-10 00:00:00 说明:匹配orderid: , 中间的最长内容

    表达式:orderid:(.*)?, 匹配结果为: 12344 说明:匹配orderid: , 中间的最短内容

    6、分组

    把正则表达式的一部分放在圆括号内,可以将它们形成组。

    我们可以对整个组使用一些正则操作,例如重复操作符:(a\d+)+ 匹配 a11a2,例如分支条件:(ab)|(yz) 匹配ab或者yz,等等。

    注意:当对组使用重复操作符时,缓存里后向引用内容会被不断刷新,只保留最后匹配的内容,需要注意括号的位置。

    例如:([abc]+)=\1 将匹配“cab=cab”,但是([abc])+=\1 却不会。

    因为([abc])第一次匹配“c”时,“\1”代表“c”;然后([abc])会继续匹配“a”和“b”。最后“\1”代表“b”,所以它会匹配“cab=b”。

    6.1 捕获

    分类

    代码

    说明

    捕获

    (exp)

    匹配exp,并捕获文本到自动命名的组里

    (?exp)

    匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name'exp)

    (?:exp)

    匹配exp,不捕获匹配的文本,也不给此分组分配组号

    注释

    (?#comment)

    这种类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅读

    • (?

    查找56,要求前面不能是4,后面必须是9。因此,可以匹配如下文本 5569  ,与4569不匹配。

    • 提取字符串 da12bka3434bdca4343bdca234bm中包含在字符a和b之间的数字,但是这个a之前的字符不能是c;b后面的字符必须是d才能提取。

    先写出含有捕获组的正则表达式:[^c]a\d*bd,

    再将其变为非捕获组的正则表达式:(?<=[^c]a)\d*(?=bd) 

    7、运算符优先级

    在构造正则表达式之后,就可以象数学表达式一样来求值,也就是说,可以从左至右并按照一个优先权顺序来求值。

    下图从上到下优先级降低,从左往右优先级降低:


     

    操作符

    说明

    \

    转义符

    (), (?:), (?=), []

    圆括号和方括号

    *, +, ?, {n}, {n,}, {n,m}

    限定符

    ^, $, \元字符, 一般字符

    位置和顺序

    |

    或操作

    示例:ab?(c|de*)+|fg 的含义:

    • 由于括号的存在,所以,(c|de*)是一个整体结构。

    • 在(c|de*)中,注意其中的量词*,因此e*是一个整体结构。

    • 又因为分支结构“|”优先级最低,因此c是一个整体、而de*是另一个整体。

    • 整个正则分成了 a、b?、(...)+、f、g。而由于分支,又可以分成ab?(c|de*)+和fg。

    8、正则表达式的书写

    例如,点号 可以匹配除换行符以外的任意字符。等价于[^\n\r]。 是最常用的符号之一,最容易被误导的符号之一。

    例:匹配具有“mm/dd/yy”(02/12/20)格式的日期,允许是其他分隔符(02.12.20 or 02-12-20)

    如下,从最粗粒度的“.”来匹配,会发现有误匹配,逐步细节化,直到满足我们的需求

    三、原理介绍

    目标字符:abbbc,匹配如下,完全按照正则的匹配顺序匹配到,分为无回溯匹配和有回溯匹配,他会先按abbbc 进行匹配,如果目标串是abbc时,在匹配第三个b时候失败,他会返回上一步然后继续匹配。

    四、hive 中涉及正则函数

    在hive 中有几个函数涉及到java 正则表达式的使用:

    -- 注意,hive中转义 转义字符,即需要两个\\;presto中则需要一个转义即可。

    1)、like: like(str, pattern) 或者 str like pattern匹配到返回true,匹配不到返回false,注意pattern中,"_"表示任意单个字符,"%"表示任意数量的字符,不支持其他正则元字符用途:查看某个数据 是否包含 一串文字

    2)、regexp_extract : regexp_extract(str,pattern(,idx)) inx为正则表达式中第几组,返回匹配的文本,

    例如:-- 0代表全部的匹配结果,分组编号代表第几个分组匹配结果
    select regexp_extract('http://a.m.taobao.com/i41915173660.htm','i([0-9]+)',0), 返回:i41915173660
    select regexp_extract('http://a.m.taobao.com/i41915173660.htm','i([0-9]+)',1) 返回:41915173660

    3)、regexp_replace :regexp_replace(str, pattern, rep)匹配到的pattern 替换为rep

    例如:-- 替换非(aceg)的字符为x
    select regexp_replace('abcdefg','[^aceg]','x') 

    4)、rlike\regexp :str rlike pattern 或者 str regexp pattern匹配到返回true,匹配不到返回false.

    -- 注意和like的区别,like的写法为: '%a%': select 'aaaa' regexp '.*a.*'

    5)、用于解析数据的例子,

    QueueWaitService.queryWaitMinutes(), request:{"waitReqDTOS":[{"cityId":344,"dpShopId":97958924,"hour":12,"minute":18,"orderViewId":"1819112605448420097958924","tableType":2,"waitTables":0},{"cityId":344,"dpShopId":97958924,"hour":12,"minute":19,"orderViewId":"1819113370427600097958924","tableType":2,"waitTables":1},{"cityId":344,"dpShopId":97958924,"hour":12,"minute":19,"orderViewId":"1819113708245220097958924","tableType":2,"waitTables":2}]}

    一般可以 用regexp_extract(`_mt_message`,'request:\\{"waitReqDTOS":(.*)\\}',1),然后拆分为多行(hive 函数 lateral view explode)最后解析json 串。

    五、使用正则的主意事项

    书写正则表达式时,我们希望可以做到精确高效

    先粗后细-从框架到细节,消除漏匹配

    先加后减-尽可能全面的匹配到后续优化,消除误匹配

    效率建议如下

    • 使用字符组代替分支条件

      • eg. 使用[a-d]表示a~d之间的字母,而不是使用(a|b|c|d),前者是一个元素,而后面是4个元素。

    • 分支顺序优化

      • 常用的字符串放在分支左边,引擎找到匹配结果就停止

    • 尽量使用边界符:^, $, \b, \B

    • 合理使用括号

      • (?:exp)不捕获匹配结果,也不分配编号,不占据缓存

    • 尽量避免使用点号元字符

    • 尽量避免使用任意量词(*,+)

      • 减少回溯

    • 对大而全的表达式进行拆解

    • 使用正则以外的方式

     

    备注:

    -- 注意,hive中转义 转义字符,即需要两个\\;presto中则需要一个转义即可。
    select regexp_replace('cab:cab2020','^([abc]+):\\1(\\d+)$','$0,name:$1,year$2')

  • 相关阅读:
    【Rust指南】详解注释|函数|条件语句|循环语句
    Java项目: 基于SSM实现教务管理系统
    造车先做三蹦子-之二:自制数据集(5x5数据集)230102
    M1(arm) Mac安装open3d
    圣诞老人遇见 GenAI:利用大语言模型、LangChain 和 Elasticsearch 破译手写的圣诞信件
    《深度学习进阶 自然语言处理》第八章:Attention介绍
    基于深度学习的车牌+车辆识别(YOLOv5和CNN)
    多网卡场景数据包接收时ip匹配规则
    深度分享:OLAP CUBE、空间换时间、MDX(上)
    野火开源资料
  • 原文地址:https://blog.csdn.net/weixin_40809627/article/details/132889399