从头开始学习正则(内容简单)
基本概念
匹配 unicode 字符
\u00e9
^ 脱字符 匹配行或者字符串起始位置
$ 美元符
匹配字面值的点号,可以使用转义 \. 或者放入字符组中 [.]
- 量词
?:0个或一个,表示字符是可选的,相当于{0,1}
+:一个或多个,相当于{1,}
*:0个或多个,相当于{0,}
{a}:待查找的字符出现的次数a次
{a,}:待查找的字符至少出现的次数a次
{a,b}:待查找的字符至少出现的次数a次,最多出现b次 - 字符组
[a-z]:[]字符组起止符,中间是可选的字符
[^\d]:字符数组取反,也就是不匹配里边这些内容,排除这些 - 简写式
\d:数字,相当于[0-9]
\w:单词字符,相当于[a-zA-Z0-9_]
\s:空白字符,包括换行,相当于[\n\t\r ]
\b:单词边界,零宽断言,不占用字符 - 元字符
^:锚位符,匹配行或者字符串起始位置
$:锚位符,匹配行或者字符串结尾位置
[]:字符组首尾
():分组
-:范围符
\:转义符
.:除了换行以外任意字符
*+?:量词,见第一点
|:或
{}:范围 - 环视
aaa (?=bbb):正前瞻
aaa (?!bbb):反前瞻
(?<=aaa) bbb:正后顾
(?<!aaa) bbb:反后顾
捕获分组和向后引用
当一个模式的全部内容或者部分内容有一对括号分组时,他就对内容进行捕获并存储于内存中,可以通过后向引用重用捕获的内容,形式为 \1 或 $1
\1 引用第一个分组内容
非捕获分组
不会将内容存储到内存中,所以有较高性能
用法:(?:the|The|THE)
原子分组
也是一种非捕获分组,可以将回溯操作关闭
用法:(?>the|The|THE)
环视
也是一种非捕获分组
量词
前面一小节已简单介绍,这节详细介绍。
贪心 懒惰 占有
量词自身是贪心的,贪心的量词会尽可能匹配更多的字符串,如果失败,会回退一个字符再次尝试。这个过程叫做 回溯 。每次回退一个字符,直到匹配或者没有字符尝试了,并且记录所有的行为。
懒惰就是非贪婪模式,每次匹配一个字符,最后匹配整个字符串。使变成懒惰只需在普通量词后面加上?
占有,只尝试一次,不会回溯使,变成占有只需在普通量词后面加上+
.* : 任意字符出现0次或多次
.*? : 非贪婪模式,匹配任意少的字符
.*+ : 独占模式,尽可能匹配,但不回溯;也就是已匹配的字符不会返还
环视
是一种非捕获分组,他根据某个模式之前或之后的内容匹配其他模式;也是零宽度断言
环视包括:
aaa (?=bbb):正前瞻
aaa (?!bbb):反前瞻
(?<=aaa) bbb:正后顾
(?<!aaa) bbb:反后顾
正前瞻
假设要匹配aaa,且紧跟其后的是bbb,这时可用正前瞻,表达式如下:
aaa (?=bbb)
因为是零宽断言,所以结果没有bbb
反前瞻
就是对正前瞻取反,要匹配aaa,且紧跟其后的不是bbb,表达式如下:
aaa (?!bbb)
仅仅把=改成!,其他不变
正后顾
正后顾会查看左边的内容,与正前瞻也是相对的;表达式如下:
(?<=aaa) bbb
与正前瞻相比,多了<,表明后顾的方向
反后顾
对正后顾取反,表达式如下:
(?<!aaa) bbb
正则示例
a+ 匹配1个或更多的a
(ab)+ 匹配1个或更多个ab
(ab | ac) ab 或 ac都可以 提取公共 a(b | c)
正则匹配过程
首先从正则表达式读取一个字符,再从字符串中取一个字符,比较,如果匹配,再获取正则下一个字符和字符串下一个字符比较,直至匹配或者没有字符了;
如果不匹配,获取字符串下一个字符继续比较。
如果是贪心的量词,会尽可能多的匹配,如果下一个正则字符匹配不上,会往前回退一个字符,重新匹配,直到匹配或没有字符。如果回溯步数太多,会导致匹配时间过长,长时间占用cpu 也就是 灾难性回溯
推荐几个网址,可在线验证测试正则,还可debug。
分析几个正则
^([ ]?[\w]{1,60})+$
- ^ 判断一行或字符串开头的零宽断言
- ( 捕获分组的左括号
- [ ]? 包含可选空格的字符组
- [\w]{1,60} 1-60位的单词字符
- ) 捕获分组的右括号
- + 1个或更多字符
- $ 判断一行或字符串结尾的零宽断言
(?=\B(\d{3})+$)
- (?= 正前瞻分组,这里匹配边界
- \B 非单词边界,这里把头尾的边界去了
- (\d{3})+ 一个或更多的3位数字
- $ 判断一行或字符串结尾的零宽断言
- ) 分组的有括号
参考文献:
- 学习正则表达式-[美]Micbael Fitzgerald