进阶表达式
一、分组
1、捕获分组
符号:()
作用:除了匹配之外,还能将需要捕获的字符、数字等提取出来
如:座机号码 021-61111111
,提取3位区号和8位座机号码,表达式如下:
/(\d{3})-(\d{8})/g
#提取结果:
#分组1:021
#分组2:61111111
如:字符串 abba-1234-ab
,提取前4中4后2的字符和数字,表达式如下:
/(\w{4})-(\d{4})-(\w{2})/g
#提取结果:
#分组1:abba
#分组2:1234
#分组3:ab
练习-提取年月日
202311
2023-1-1
20230101
2023-01-01
2023/01/01
2023.01.01
2023 1 1
\(\d{4})[\-\/.\s]?(\d{1,2})[\-\/.\s]?(\d{1,2})\g
# (\d{4}) =>捕获分组,\d{4}=>提取4个数字 ,匹配出2023
# [\-\/.\s] =>匹配符号[-/. ] (其中:\=>转义符,\s=>空白字符)
# ? =>可选匹配=>即前面有没有符号都能匹配到,如202311和20230101))
# (\d{1,2}) =>捕获分组,\d{1,2}=>提取1-2个数字,匹配出1或者01
或者条件
符号:|
作用:"或"操作,将匹配条件写在()
中,使用|
隔开。
如:匹配 seen 或 seem,表达式如下:/see(n|m)/g
,注:"或"操作,只会捕获到1个分组n或m
2、非捕获分组
符号:(?: 表达式)
作用:有的时候需要用到()
的特性,但并不需要捕获分组
如:下列字符串,只提取中间4位数字
0000-1234-78
000/1234/00
num:5678:89
\(?:\d{3,4}|num)[\:\-\/](\d{4})[\:\-\/](?:\d{2})\g
# (?:\d{3,4}|num) => 非捕获分组,匹配3-4个数字或num
# [\:\-\/] =>匹配符号[:-/]
# (\d{4}) => 捕获分组,匹配4个数字
#(?:\d{2}) => 非捕获分组,匹配2个数字
3、分组的回溯引用
符号:\n
作用:引用分组,引用在前半部分中定义的分组
如:字符串<ab>ba</ab>
和<ab>ba</cd>
,使用表达式<(\w+)>.*</\1>
,匹配到<ab>ba</ab>
其中:(\w+)
捕获分组了ab
,那么\1
=>引用了第1个分组(即:(\w+)
) ,</\1>
=></ab>
练习-匹配ab、ba这种形式的字符串
abcddcef
effeiijk
lithhto
/(\w)(\w)\2\1/g
# 举例:abcddcef
# (\w)(\w) =>每2个字符为1个范围,如:(a)(b)、(c)(d)、(d)(c)、(e)(f)
# 其中:2对括号将范围分成了2组,比如(c)(d),第1组是c,第2组是d
# \2=>引用第2组d,\1=>引用了第1组c,那么 \2\1=>dc
# (\w)(\w)\2\1 =>匹配到了字符串中的cddc
二、断言 也叫环视
1、正向先行断言
符号:(?= 表达式)
作用:匹配在表达式前的字符(相当于从左往右看)
如:https://www.baidu.com 和 https://baidu.com
,需匹配含有www
的网址,表达式 https://(?=www).+
,则匹配出https://www.baidu.com
https://(?=www)
表达式从左往右匹配出:从开始
到www
之间的https://
#### 练习-密码强度验证 `UySRo49ps 8848 Ig7AHzZ0J qwe` 要求:至少1个大写字母、至少1个小写字母、至少1个数字、至少8个字符
/(?=.*?[a-z])(?=.*?[A-Z])(?=.*?\d).{8,}/g
# (?= ...) 是正向先行断言的表达式
# .*? =>表示至少有1个任意字符
# (?=.*?[a-z]) =>至少1个小写字母
# (?=.*?[a-z])(?=.*?[A-Z])(?=.*?\d) =>依次类推,至少1个小写字母,至少1个大写字母,至少1个数字
# {8,} =>至少8个字符
# 结果匹配出:UySRo49ps、Ig7AHzZ0J
2、反向先行断言
符号:(?! 表达式)
作用:保证表达式的右边不能出现某字符
如:https://www.baidu.com 和 https://baidu.com
,需匹配"不含"www
的网址,表达式 https://(?!www.).+
,则匹配出https://baidu.com
https://(?!www.)
意思是https://
的右边不能出现www
练习-排除邮箱
abc@sina.com test@qq.com qq@163.com 163@qq.com
匹配不是qq邮箱的数据
/.*?@(?!qq.com)/g
# .*?@ =>表示@前可以是任意字符
# (?! ...) 是反向先行断言的表达式
# (?!qq.com) =>排除含有qq.com的字符串
# 结果匹配出:abc@sina.com、qq@163.com
3、正向后行断言
符号:(?<= 表达式)
作用:匹配在表达式后的字符(相当于从右往左看)
如:https://www.baidu.com 和 http://baidu.com
,需匹配"含"https
的网址,表达式 .*?(?<=https://).+
,则匹配出https://www.baidu.com
(?<=https://)
表达式从右往左匹配出www
后与https://
之间的空格
练习-匹配含有王姓的名字
王五
李四 小王
张三 王五五
大王
/(?<=王).+/g
# (?<= ...) 是正向后行断言的表达式
# (?<=王) =>从右往左匹配字符串中含有王的,这里把所有含有王的都匹配到了
# (?<=王).+ =>表达式后面至少有1个字符,那么王后面没有字符的则会排除掉
结果匹配出:王五、王五五
4、反向后行断言
符号:(?<! 表达式)
作用:保证表达式的左边不能出现某字符
如:https://baidu.com 和 http://baidu.com
,需匹配"不含"https://
的网址,表达式 .+(?<!https://)baidu.com
,则匹配出http://baidu.com
(?<!https://)baidu.com
意思是baidu.com
的左边不能出现https://
练习-匹配左右两边是$
,且只有1个$
的字符串
abc$asddadd$$
$123$
$ A = a / b + b $
$$ a=b^2 $$
/(?<!\$)\$(?!\$).+(?<!\$)\$(?!\$)/g
# (?<!...) 是反向后行断言的表达式,即表达式的左边不能出现某字符
# (?! ...) 是反向先行断言的表达式,即表达式的右边不能出现某字符
# (?<!\$)\$(?!\$) => $的左右都不能再出现$,这样保留了1个$
# (?<!\$)\$(?!\$).+(?<!\$)\$(?!\$) =>以此类推,左右两边都有$,且都只有1个$
结果匹配出:$123$、$ A = a / b + b $