正则匹配详解
1. 元字符
字符 | 描述 | 应用 |
---|---|---|
\ | 将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符 | ‘n’ 匹配字符 “n”。’\n’ 匹配一个换行符。序列 ‘\’ 匹配 “” 而 “(” 则匹配 “(”。 |
. | 匹配除换行符之外的任何单字符 | |
^ | 匹配输入字符串的开始 | 例如 ^a ,表示 字符串必须以a开头,才会继续匹配,如果不是以a开始,则返回空 |
$ | 表示匹配字符串的结尾 | 例如 a$ ,表示 字符串必须以a结尾,如果不是以a结尾,则返回空 |
\b | 匹配一个单词边界 | 例如, ‘er\b’ 可以匹配"never" 中的 ‘er’,但不能匹配 “verb” 中的 ‘er’。 |
\s | 匹配所有空白符,包括换行 | |
\S | 匹配非空白符,不包括换行 | |
\w | 匹配字母、数字、下划线或汉字 | |
\d | 表示匹配一个数字字符,等同于[0-9] | |
\D | 表示匹配一个非数字字符,等同于 [^0-9] | |
| | 表示 或 | a|b 表示匹配 a 或者b |
[^] | 表示不匹配集合中的任何元素 | [^0-9] 表示匹配非数字字符, [^a-zA-Z] 表示匹配非英文字符 |
[] | 表示匹配集合中的任何一个元素 | [abc] 表示匹配a、b、c 三个元素中的一个, [a-z] 表示 匹配任意小写英文字符,[A-Z] 表示匹配任意大写英文字符,[0-9]表示匹配任意一个数字 |
() | 标记一个子表达式的开始和结束位置。要匹配这些字符,请使用 \( 和 \) |
2. 重复限定符
字符 | 功能描述 | 应用 |
---|---|---|
* | 匹配前一个位置的字符0次或多次 | ba* 可以匹配 b,ba,baa,baaaa |
+ | 匹配前一个位置的字符1次或多次 | ba* 可以匹配到 ba,baa,baaaa 但是匹配不到b |
? | 匹配前一个字符 0次或者1次,或指明一个非贪婪限定符 | ba? 只能匹配到 b 、ba |
{n} | 表示匹配元素n次 | a{3} 表示匹配的字符串为 aaa |
{n,} | 表示匹配元素大于等于n次 | a{3} 表示匹配的字符串为 aaa,aaaa,aaaaaa |
{n,m} | 表示匹配字符次数在n和m次之间 | a{3,5} 表示匹配的字符串为 aaa aaaa aaaaa 这三种 |
应用举例
-- 1.匹配8位数字的QQ号码:
^\d{8}$
--2. 匹配1开头11位数字的手机号码
^1\d{10}$
--3. 匹配以a开头的,0个或多个b结尾的字符串
^ab*$
-- 4. 匹配字符串中包含0到多个ab开头
^(ab)*
--5. 要匹配以(ab)开头
^(\(ab\))*
--6. 联通有130/131/132/155/156/185/186/145/176等号段,假如让我们匹配一个联通的号码
^((13[0-2])|(15[56])|(18[5-6])|145|176)\d{8}$
*
和 +
限定符都是贪婪的,因为它们会尽可能多的匹配文字,只有在它们的后面加上一个 ?
就可以实现非贪婪或最小匹配。
-- 字符串: string= "<h1>RUNOOB-菜鸟教程</h1> "
<.*> -- 匹配整个字符串
贪婪模式:在贪婪匹配下,.*
会匹配尽可能多的字符。使用 .*
的话就可以匹配任意长度的任意字符
上面的表达式匹配从开始小于符号 <
到关闭 h1
标记的大于符号 >
之间的所有内容。
<.*?>/ -- 只会匹配0或1次第一个< >中的内容 当.*?匹配到h1时,再往后的字符就是>,而>恰好可以匹配
非贪婪模式:非贪婪匹配就是尽可能匹配少的字符
如果您只需要匹配开始和结束 h1
标签,下面的非贪婪表达式只匹配 <h1>
。
<.*?>/ --只会匹配0或1次第一个< >中的内容 当.*?匹配到h1时,再往后的字符就是>,而>恰好可以匹配
**注:**但是这里需要注意,如果匹配的结果在字符结尾,.*?
就有可能匹配不到任何结果了,因为他会尽可能匹配少的字符,例:
select regexp_extract('hello 1234567 world/python','he.*?(\\d).*rld/(.*?)',2) -- 返回为空
select regexp_extract('hello 1234567 world/python','he.*?(\\d+).*rld/(.*)',2) -- python
3. SQL 中正则匹配
3.1. 正则匹配
语法: regexp_extract(string subject, string pattern, int index)
说明: 将字符串subject
按照pattern
正则表达式的规则拆分,返回index
指定的字符。
---语法事例:
---regexp_extract 从起始位置开始匹配,当匹配到目标后,便停止匹配,返回index指定的group对应的字符串,每个() 表示一个group
SELECT regexp_extract('asbdad100-200喜马拉雅', '(\\d+)-(\\d+)', 1);
---regexp_extract_all 从起始位置开始匹配,当匹配到目标后,仍然继续匹配,生成一个大的group,返回每个sub_group中index对应的字符串
SELECT regexp_extract_all('100-200, 300-400', '(\\d+)-(\\d+)', 1);
3.2 正则替换
-- 使用字符串num替换匹配到的所有字符串
SELECT regexp_replace('100-200,300-400', '(\\d+)', 'num');
3.3 应用实例
-- 1. regexp_replace用法
-------- a. 截取字符串中的汉字部分
select regexp_replace('七夕节comming!来啦','([^\\u4E00-\\u9FA5]+)','') --- 七夕节来啦
-------- b. 截取字符串中字母和数字的部分
select regexp_replace('wo爱你123CHINA中国!','([^a-zA-Z0-9]+)','') --- wo123CHINA
-------- c. 将字符串中英文和数字的组合替换
SELECT regexp_replace('七夕节Coming666!','([a-z]+|[A-Z]+|[0-9]+)','')
-- 2. regexp_extract用法
select regexp_extract('ab3.35_52-36_53-34_51.1063ef','(.*\\.)(\\d+.*\\d)(\\..*)',2)
select regexp_extract('七夕节coming666','([0-9]+)',1) ---- 666
select regexp_extract('152天内有67天无通话记录','([0-9]+).*([0-9]+)',1) . ----- 152
select
id,
-- 相似应用: transfrom filter
regexp_replace(last_30d_ai_label_play_map,'(地域[^,]*,)|(,地域[^,]*\\d)|(地域[^,]*\\d$)','') as last_30d_ai_label_play_map
from xxx where last_30d_ai_label_play_map
like "%地域%"
as res;
transfrom
函数,处理数据应用实例:数据中出现类似:
郑渊洁:1.0,好习惯:0.33,郑渊洁给孙女的好习惯书:十二生肖童话绘本:0.75,孙女:0.67 的脏数据
select
id,
nlp_labels_intros,
concat_ws(',',transform(split(nlp_labels_intros,','), x -> if(size(split(x,':'))=3, concat(split(x,':')[0],split(x,':')[1],':',split(x,':')[2]) , x))) as label
from xxxx
select
cast( album_id as string) as album_id ,
-- 使用非贪婪匹配模式
split(regexp_replace(regexp_extract_all(get_json_object(label_group, '$.labels_ai'),'(t".")(.*?)(})',2 ),'\\]|\\[|","w"','') ,',') as nlp_labels_ai,
split(regexp_replace(regexp_extract_all(get_json_object(label_group, '$.labels_app'),'(t".")(.*?)(})',2 ),'\\]|\\[|","w"','') ,',') as nlp_labels_app,
split(regexp_replace(regexp_extract_all(get_json_object(label_group, '$.labels_conp'),'(t".")(.*?)(})',2 ),'\\]|\\[|","w"',''),',' ) as nlp_labels_conp,
split(regexp_replace(regexp_extract_all(get_json_object(label_group, '$.titles'),'(t".")(.*?)(})',2 ),'\\]|\\[|","w"',''),',') as nlp_labels_titles,
split(regexp_replace(regexp_extract_all(get_json_object(label_group, '$.intros'),'(t".")(.*?)(})',2 ),'\\]|\\[|","w"','') ,',') as nlp_labels_intros,
'$current(yyyyMMdd,-1)' as dt
from xxxxx
as res;
sublime中正则表达式的使用:
来源:识醉沉香