正则表达式
元字符
| 字符 | 含义 |
|---|---|
\ |
将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符 |
^ |
匹配行首位置 |
$ |
匹配行尾位置 |
\b |
匹配一个单词边界,也就是指单词和空格间的位置 |
\B |
匹配非单词边界 |
\d |
匹配一个数字字符。等价于 [0-9] |
\D |
匹配一个非数字字符。等价于 [^0-9]。 |
\s |
匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。 |
\S |
匹配任何非空白字符。等价于 [^ \f\n\r\t\v] |
\w |
匹配字母、数字、下划线。等价于[A-Za-z0-9_] |
\W |
匹配非字母、数字、下划线。等价于[^A-Za-z0-9_] |
\xn |
匹配 n,其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,\x41 匹配 "A"。\x041则等价于 \x04 & 1。正则表达式中可以使用 ASCII 编码。 |
\cx |
匹配由 x 指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 c字符。 |
\f |
匹配一个换页符。等价于 \x0c 和 \cL |
\r |
匹配一个回车符。等价于 \x0d 和 \cM |
\n |
匹配一个换行符。等价于 \x0a 和 \cJ |
\t |
匹配一个制表符。等价于 \x09 和 \cI |
\v |
匹配一个垂直制表符。等价于 \x0b 和 \cK |
限定符
限定符用于限定表达式匹配内容的出现次数
| 限定符 | 含义 |
|---|---|
expr* |
expr所匹配的内容可以出现零次或多次 |
expr+ |
expr所匹配内容可以出现一次或多次 |
expr? |
expr所匹配的内容可以出现零次或一次 |
expr{n} |
expr所匹配的内容只能出现n次 |
expr{n,} |
expr所匹配的内容至少出现n次 |
expr{n,m} |
expr所匹配的内容至少出现n次,至多出现m次 |
注意:
expr*和expr+形式的限定符默认采用贪婪模式,如果采用非贪婪模式,则使用expr*?和expr+?即可。
贪婪与非贪婪
贪婪匹配:正则表达式一般趋向于最大长度匹配,也就是所谓的贪婪匹配。
非贪婪匹配:就是匹配到结果就好,就少的匹配字符。
如: 对于文本内容: abcaxc
如使用ab.*c匹配文本内容,结果就是匹配到:abcaxc整个字符串。
如使用ab.*?c匹配字符串文本内容,结果就是匹配到:abc。
分组
将表达式做成一个单元,方便对表达式匹配的内容进行捕获
分组类型
捕获分组
| 格式 | 含义 |
|---|---|
(expr) |
expr为表达式内容,没有组名,只能通过该分组在整个正则中的分组顺序获取其匹配的内容 |
(?expr) |
通过groupname指定分组名称,可以通过组名或者顺序获取匹配内容 |
非捕获分组
| 格式 | 含义 |
|---|---|
(?:expr) |
?:在表达式之前,表示该分组只做匹配,不捕获其内容,例如:industr(?:y|lies) 会匹配industry或industries,但只捕获industr |
零宽(断言|预查)
| 格式 | 含义 |
|---|---|
(?=expr) |
零宽度正向肯定预查, 英文:look ahead positive assert 仅当子表达式 expr在 此位置的右侧匹配时才继续匹配 例如,Windows(?=95|98|NT|2000)能匹配windows2000中的windows,但是不能匹配windows7中的windows。 |
(?!expr) |
零宽度正向否定预查,英文:look ahead negative assert 仅当子表达式 expr不在此位置的右侧匹配时才继续匹配 例如,Windows(?!95|98|NT|2000)不能匹配windows2000中的windows,但是能匹配windows7 或 windows10中的windows,也能匹配windows中的windows。 |
(?<=expr) |
零宽度负向肯定预查,look behind positive assert 仅当子表达式 expr在此位置的左侧匹配时才继续匹配 例如,(?<=95|98|NT|2000)Windows能匹配2000windows中的windows,但是不能匹配7windows中的windows。 |
(?<!expr) |
零宽度负向否定预查,look behind negative assert 仅当子表达式 expr不在此位置的左侧匹配时才继续匹配 例如,(?<!95|98|NT|2000)windows不能匹配2000windows中的windows,但是能匹配7windows 或 10windows中的windows,也能匹配windows中的windows。 |
预查不消耗字符:也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
分组的使用
分组的次序
在表达式 (expr1)(expr2(expr3))中,存在四个这样的组:
| 0 | (expr1)(expr2(expr3)) |
|---|---|
| 1 | (expr1) |
| 2 | (expr2(expr3)) |
| 3 | (expr3) |
第0组始终是整个表达式本身,分组有嵌套的话,先从外部分组开始计。
反向引用
一个分组所匹配的内容是可以被其他分组引用的。就拿匹配<title>.*</title>标签来说,就可以写成<(title)>.*</\1>
其中\1,就是对(title)分组的引用,1表示(title)在表达式中的次序。
注意:反向引用的作用是引用分组所匹配的内容,而不是分组所代表的正则表达式本身。例如:如果我们需要匹配一个IP地址,可以使用\d{1,3}(.\d{1,3}){3}这个正则,我们会发现\d{1,3}片段出现了两次,有人可能会觉得可以使用反向引用进行简化:(\d{1,3})(.\1){3}。但是这个表达式是不正确的,它只能匹配123.123.123.123 或192.192.192.192这类四个段都为一个数字的IP地址,而不能匹配192.168.119.91这样的IP地址。可以看出反向引用是引用分组所匹配的内容,而不是分组所代表的正则表达式本身。
侵占模式
匹配成功不进行回溯,与侵占量词“+”可以通用,比如:\d++ 可以写为 (?>\d+)
举例侵占模式:
将一些多位的小数截短到三位小数:`\d+\.\d\d[1-9]?\d+`。在这种条件下 `6.625` 能进行匹配,这样做没有必要,因为它本身就是三位小数。最后一个`5`本来是给 `[1-9]` 匹配的,但是后面还有一个 `\d+` 所以,`[1-9]` 由于是`?`可以不匹配所以只能放弃当前的匹配,将这个`5`送给 `\d+` 去匹配,如果改为:`\d+\.\d\d[1-9]?+\d+`的侵占形式,在`5`匹配到 `[1-9]` 时,由于是侵占式的,所以不会进行回溯,后面的 `\d+` 就匹配不到任东西了,所以导致 `6.625` 匹配失败。
这种情况,在替换时就有效了,比如把数字截短到小数点后三位,如果正好是三位小数的,就可以不用替换了,可以提高效率,侵占量词基本上就是用来提高匹配效率的。把 `\d+\.\d\d[1-9]?+\d+` 改为 `\d+\.\d\d(?>[1-9]?)\d+` 这样是一样的。
浙公网安备 33010602011771号