zoukankan      html  css  js  c++  java
  • HiveSQL正则表达式的应用[转]

    最近工作中数据处理方面用到很多不是特别容易处理的数据,用正则表达式的话会让语句显得特别精简,也可以用各种字符串截取函数嵌套处理(必须要有一定规律),总结一下经常用到的几个。

    1.正则的通配符简介
       1)正则表达式的符号及意义   
           ^ 表示开头

          $ 表示结尾

          . 表示任意字符

          * 表示任意多个

    /
    做为转意,即通常在"/"后面的字符不按原来意义解释,如/b/匹配字符"b",当b前面加了反斜杆后//b/,转意为匹配一个单词的边界。
    -或- 
    对正则表达式功能字符的还原,如"*"匹配它前面元字符0次或多次,/a*/将匹配a,aa,aaa,加了"/"后,/a/*/将只匹配"a*"。

    ^ 匹配一个输入或一行的开头,/^a/匹配"an A",而不匹配"An a"
    $ 匹配一个输入或一行的结尾,/a$/匹配"An a",而不匹配"an A"
    * 匹配前面元字符0次或多次,/ba*/将匹配b,ba,baa,baaa
    + 匹配前面元字符1次或多次,/ba*/将匹配ba,baa,baaa
    ? 匹配前面元字符0次或1次,/ba*/将匹配b,ba
    (x) 匹配x保存x在名为$1...$9的变量中
    x|y 匹配x或y
    {n} 精确匹配n次
    {n,} 匹配n次以上
    {n,m} 匹配n-m次
    [xyz] 字符集(character set),匹配这个集合中的任一一个字符(或元字符)
    [^xyz] 不匹配这个集合中的任何一个字符
    [/b] 匹配一个退格符
    /b 匹配一个单词的边界
    /B 匹配一个单词的非边界
    /cX 这儿,X是一个控制符,//cM/匹配Ctrl-M
    /d 匹配一个字数字符,//d/ = /[0-9]/
    /D 匹配一个非字数字符,//D/ = /[^0-9]/
    /n 匹配一个换行符
    /r 匹配一个回车符
    /s 匹配一个空白字符,包括/n,/r,/f,/t,/v等
    /S 匹配一个非空白字符,等于/[^/n/f/r/t/v]/
    /t 匹配一个制表符
    /v 匹配一个重直制表符
    /w 匹配一个可以组成单词的字符(alphanumeric,这是我的意译,含数字),包括下划线,如[/w]匹配"$5.98"中的5,等于[a-zA-Z0-9]
    /W 匹配一个不可以组成单词的字符,如[/W]匹配"$5.98"中的$,等于[^a-zA-Z0-9]。
    '( )' 标记一个子表达式的开始和结束位置。
    '[]' 标记一个中括号表达式。
    /num 匹配 num,其中 num 是一个正整数。对所获取的匹配的引用。

       2)字符簇: 
            [[:alpha:]] 任何字母。
            [[:digit:]] 任何数字。
            [[:alnum:]] 任何字母和数字。
            [[:space:]] 任何白字符。
            [[:upper:]] 任何大写字母。
            [[:lower:]] 任何小写字母。
            [[:punct:]] 任何标点符号。
            [[:xdigit:]] 任何16进制的数字,相当于[0-9a-fA-F]

            [[:<:]],[[:>:]] 标记表示word边界。它们分别与word的开始和结束匹配。word是一系列字字符,其前面和后面均没有字字符。字字符是alnum类中的字母数字字符或下划线(_)

       3)各种操作符的运算优先级:
               / 转义符
              (), (?:), (?=), [] 圆括号和方括号
               *, +, ?, {n}, {n,}, {n,m} 限定符
              ^, $, anymetacharacter 位置和顺序

    2.正则函数介绍
       1) regexp_extract
    regexp_extract(str  , regexp  , idx)     

    参数解释:

    其中:

    str是被解析的字符串或字段名

    regexp 是正则表达式

    idx是返回结果 取表达式的哪一部分  默认值为1。

    0表示把整个正则表达式对应的结果全部返回

    1表示返回正则表达式中第一个() 对应的结果 以此类推 

    For example :   

           select regexp_extract('hitdecisiondlist','(i)(.*?)(e)', idx ) ;     ----   (.*?) 代表  0到多个任意字符,?代表非贪婪模式,意思是:取尽量少的任意字符

           idx=0  结果:itde  ; idx=1  结果:i  ; idx=2 结果:td  ; idx=3 结果:e

          由此可以看出从左开始括号内部的值是根据 idx的下标来确定的(起始位为1)

          select  regexp_extract('insert overwrite table tmp_table_test  select * from table' , '(table)[[:space:]](.*)[[:space:]](select)',2) from dual 

           目的是取出要插入数据的目标表的表名(tmp_table_test) ,位置为2时 取得是(.*)匹配的字符串,位置为1时取得是(table)匹配的字符串 table,位置为3时取得是 (select)匹配的字符串 select

         select
                 REGEXP_EXTRACT('9.00w','([0-9]*)[[:punct:]]([0-9]*)[[:alpha:]]',1),
                 REGEXP_EXTRACT('9.00w','([0-9]*)[[:punct:]]([0-9]*)[[:alpha:]]',2)
          from dual

          大家可以试试这个语句的作用,验证一下上面说的是否正确,^_^

        2) regexp_substr
    regexp_substr(string, regex,postion,match_parameter)

      string : 被解析的字符串或字段名

      regex: 正则表达式

      postion:其实位置

      match_parameter:出现的次数

    For example:

                      select regexp_substr('别克-君威2010款 2.4L A.MT 旗舰版2.3T','[[:alnum:]][[:punct:]][[:alnum:]][LT]',1,1)  from dual

                     分析: 上面正则的意思是 [[:alnum:]][[:punct:]][[:alnum:]][LT]  ===> 任何字母(不区分大小写)和数字+ 任何标点符号+任何字母和数字 +(L或者T)的组合

                      后面   1,1 的意思是从匹配的字符串起,符合正则且第一次出现的字符串

                      结果:  2.4L

                     

                     换个方式提取  A.MT SQL语句如下

                    select regexp_substr('别克-君威2010款 2.4L A.MT 旗舰版2.3T','[[:alnum:]][[:punct:]][[:alnum:]][LT]',1,2)  from dual

                    如果提取2.3T ,把最后那个数字改成3即可,就不写sql了。累!

                    

                     select
                     REGEXP_SUBSTR('9.00w','([0-9]*)[[:punct:]]([0-9]*)',1,1) 
                     from dual

                    大家可以验证一下这个语句!

          3)regexp
     regexp的用法比较简单,就是个判断语句跟like、=、!=、not in 、in 的感觉一样

              大家日常处理日期数据时,会出现yyyy-mm-dd这种不符合正常逻辑的情况,例如:1870-12-59/2018-02-29(瑞年和平年的问题) 等

           废话不多说,直接上例子

    select 1 from dual 
    where '2017-09-31' REGEXP '(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))-02-29)' 

                        来把下面的表达式解剖了来看

                                                           '(([0-9]{3}[1-9]|     ----第一种组合前3位满足0~9,后1位满足1~9   (YYYY)

                                                             [0-9]{2}[1-9][0-9]{1}|    ----第二种组合前2位满足0~9,后1位满足1~9,最后1位满足0~9  (YYYY)

                                                            [0-9]{1}[1-9][0-9]{2}|     ----第三种组合第1位满足0~9,第2位满足1~9,最后2位满足0~9  (YYYY)

                                                            [1-9][0-9]{3})                ----第四种组合第1位满足1~9,后3位满足0~9  (YYYY)

                                                            -(((0[13578]|                ----第一种组合第1位是0,第2位 13578 (中括号 [  ]代表里面的元素是或的概念)  (MM)   01 03 05 07 08

                                                                       1[02])               ----第二种组合第1位是1,第2位 02   (MM)   10 12

                                                            -(0[1-9]|                       ----第一种组合第1位是0,第2位 1~9    (DD)   01 ~ 09

                                                               [12][0-9]|                  ----第一种组合第1位是1或2,第2位 0~9    (DD)  10 ~29

                                                               3[01]))|                     ----第一种组合第1位是3,第2位  0或1   (DD)   30~31

                                                           上面考虑的是1 3 5 7 8 10 腊  31天永不差的原则,这个不会的话重读一边小学!

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

                                                           ((0[469]|                      ----第一种组合第1位 0 ,第2位 469 (中括号 [  ]代表里面的元素是或的概念) (MM) 04 06 09

                                                                   11)                      ----第二种组合是11  (MM)    11

                                                            -(0[1-9]|                     ----第一种组合第1位0,第2位 1~9   (DD) 01~09

                                                            [12][0-9]|                    ----第二种组合第1位1~2,第2位 0~9   (DD)  10~29

                                                            30))|                           ----第三种组合30   (DD)    30

                                                          上面考虑的是 4 6 9 11 月 都是30天

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

                                                        下面考虑的是瑞年、平年2月多少天的问题。

                                                           (02-(0[1-9]|[1][0-9]|2[0-8]))))|

                                                           ((([0-9]{2})(0[48]|

                                                           [2468][048]|

                                                           [13579][26])|

                                                           ((0[48]|[2468][048]|[3579][26])00))-02-29)'

      

    正则表达式的函数太多了,先总结三个,如果还想看请点赞,凑齐20赞召唤我继续更新,包括上面缺了一块儿的日期问题,我补充完整
    ---------------------
    作者:冯剑
    来源:CSDN
    原文:https://blog.csdn.net/u010215845/article/details/83275598
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    jaxb解析xml工具类
    JQuery的父、子、兄弟节点查找方法
    jw player 配置参数
    jQuery判断当前元素是第几个元素&获取第N个元素
    正则表达式中test,match,exec区别
    php常用函数file
    php常用函数time
    php常用array函数
    php常用string函数
    Linux常用命令
  • 原文地址:https://www.cnblogs.com/cwind/p/10273892.html
Copyright © 2011-2022 走看看