“正则”怎么理解?
正则表达式对应的英文是 Regular Expression, 直译为规则而整齐的表达式。
正则是一个汉语词汇,基本意思是正其礼仪法则;正规;常规;正宗等。出自《楚辞·离骚》、《插图本中国文学史》、《东京赋》等文献。
不要纠结名字,就是一种表达式写法的命名而已。
推荐使用在线正则验证工具 练习使用正则,切换至PCRE Engine(支持的正则语法更全)
要点1: 单字符的匹配
一“点”代所有
.可匹配所有字符(注:在多行模式下,不能匹配换行符)
转义即所见
在正则表达式中,既然.能表示所有字符,那么只想匹配“点”字符呢? 只需在“点”前面加上 符号即可,这个符号就被命名为转义字符了。
如果想匹配怎么办? 前面再加一个转义字符就是了: \
中括涵范围
中括号中写上字符范围、或一系列指定字符,那么将只匹配这个范围内的字符。
-
比如 [1234567890]只匹配数字, [abcACB]只匹配字母a、b、c, A、B、C
-
匹配一个范围还可以这么写 [0-9], 匹配所有英文字母 [a-zA-Z]
注意到,上面定义范围时使用了- ,它是严格按照ASCII码表的前后顺序定义的,只能是a-z, 而不能是z-a, 附ACSII码截图
要点2: 字符集缩写
预热: 先看几个英文单词
-
digit
-
word
-
space
正题
-
d 是字符范围 [0-9] 的缩写
-
w 是字符范围 [0-9a-zA-Z_]的缩写
-
s 表示一个空格
他们的对立面--将字母换成大写
-
D 非数字
-
W 非文本
-
S 非空格
要点3: 数量限制
-
0个或1个: ?
-
1个或多个: +
-
0个或多个:*
-
m个到n个: {m, n}
-
m个: {m}
应用举例:
实验文本: `aaab`
-
a?b 返回匹配结果 ab
-
a+b 返回匹配结果 aaab
-
a*b 返回匹配结果 aaab
-
a{1,2}b 返回匹配结果 aab
-
a{2}b 返回匹配结果 aab
思考
从上述实例,为什么匹配时虽加了数量限制,但是确始终返回最多的匹配结果? 比如,+表示1个或多个,在a+b中没有返回ab,而是直接返回了3个a的aaab
贪婪与非贪婪
默认是贪婪的,匹配数量时尽可能多。
若在量词后添加?修饰符,则变成 非 贪婪(也可以叫懒惰),匹配数量时尽可能少
要点4: 文本边界
始于奋斗(向上冲),死于金钱
-
一行的开头 ^
-
一行的结果 $
高级的
-
w与 W 之间的 不可知地(出自小说《将夜》,看不到摸不着,但确实存在的地方) -------
思考: 对于文本 "chenjihu@gmail_gmail.com",我只想匹配第一个gmail,该如何做?
扩展知识点
-
单行模式: 多行文本当成一行,只有一个开头和结尾
-
多行模式:多行文本就是多行,每行都有一个开头和结尾
要点5: 分组、或
场景:
有文本 ”win10 is windows, win9 is windows", 想要一步将其中的win10和win9中的win替换成 windows+空格,如何做?
正则里用 小括号给要匹配的文本扩上,便于引用和替换,这就是分组。
上例中 使用 wind+ 可以匹配上win10和win9,想要保留 10和9,替换掉前面的win,可以将数字部分放在一个组内,替换时这个组不动,组外的部分设为空字符即可。
win(d+) 匹配后使用 $1替换,win被替换没了,$1表示第一个组内的内容。
高级用法-反向引用
还是使用同一个场景,需要匹配出文本 "win10 is win" 和“win9 is win”
发现规律-匹配出的文本前后都有win
可以这样写: win.*?win win.+?win
也可以使用反向引用: (win).*?1 ,其中的1 代指前面的第一个分组内容
或 |的用法
还是前述字符串,只想替换win9、windows 为winXP,怎么做?
答案: (win9|windows) 匹配后,替换文本为 winXP
要点6: 正向预查和负向预查
文本 ”win10 is windows, win9 is windows", 想将其中所有的win10,win9中的数字替换为XX。
可以使用前面所介绍的分组特性来做: (win)d+ 替换为 $1XX
-
正向预查: win(?=10) 查出所有其后为10的win
-
负向预查: (?<=win)10 查出所有其前面是win的数字10, 前端Javascript不支持这个语法。 实现前例同样功能的表达式 (?:win)d+ 替换用 XX即可, 请自行比较不同
要点7: 非捕获分组
非捕获分组的语法是 (?:不会创建组)
所谓的非捕获,就是匹配时不会为它创建一个分组,替换时也无法使用 $1,$2等找到引用它。
要点8: if else (高级,可选)
(abc)?de(?(1)f|w) 若匹配上abc,则de后匹配f,否则匹配w
对于字符串 "abcdew", 匹配出的结果是dew , 对于字符串“abcdefw” 匹配出的结果是 abcdef