一 概念
概念:正则表达式(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,并捕获文本到名称为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。
备注:
-- 注意,hive中转义 转义字符,即需要两个\\;presto中则需要一个转义即可。
select regexp_replace('cab:cab2020','^([abc]+):\\1(\\d+)$','$0,name:$1,year$2')