对于正则表达式一向了解不多,假期期间随着《正则表达式必知必会》快速学习了一下正则表达式的基本使用,在此记录一下。
正则表达式语法笔记
常用元字符
| 元字符 | 作用 |
|---|---|
| . | 换行符外任意字符 |
| \d | 一个数字,等价于 [0-9] |
| \D | 一个非数字,等价于 [^0-9] |
| \w | 一个数字、字符及下划线,等价于[a-zA-Z0-9_](最后一个是下划线_) |
| \W | 一个非数字、字符和下划线,等价于[^a-zA-Z0-9_](最后一个是下划线_),注意,[]内的 ^,对之后每个组合都取非,不只是紧接的 |
| \s | 一个空白字符,等价于[\f\n\r\t\v ](最后有个空格),换页、换行、回车、制表、垂直制表符、空格 |
| \S | 一个非空白字符,等价于[^\f\n\r\t\v ](最后有个空格) |
要注意,[]内出现的的元字符对应字符,不按照元字符处理,不需要要转义,如“.”、“$”等
重复匹配
| 表达式 | 作用 |
|---|---|
| +,[]+ | 匹配前面字符/集合的一次或多次,贪婪 |
| *,[]* | 匹配前面字符/集合的零次或多次,贪婪 |
| ?,[]? | 匹配前面字符/集合的零次或一次,等价于{0,1} |
| +? | +的懒惰情况 |
| *? | *的懒惰情况 |
| {n},[]{n} | 字符或集合出现 n 次 |
| {n,m},[]{n,m} | 字符或集合出现 n 到 m 次 |
| {n,},[]{n,} | 字符或集合出现 n 到无穷次/至少 n 次,贪婪 |
| {n,}?,[]{n,}? | {n,},[]{n,}的懒惰情况 |
关于贪婪和懒惰,可见例子:
1 | <B>AK</B> and <B>HI</B> |
使用
1 | <B>.*</B> |
将匹配到
1 | <B>AK</B> and <B>HI</B> |
而懒惰形式
1 | <B>.*?</B> |
将匹配到
1 | <B>AK</B> |
和
1 | <B>HI</B> |
边界
| 表达式 | 作用 |
|---|---|
| \b | 单词边界,相当于 \w 和 \W 之间的位置 |
| \B | 非单词边界,即 字母数字下划线之间 或 非字母数字下划线之间 |
| ^ | 匹配字符串开头 |
| $ | 匹配字符串结尾 |
| (?m) | 加在最前,使 ^ 和 $ 匹配行内字符串开头和行内字符串结尾。ps:不一定每种语法都适用 |
| \A | 同 ^,但 (?m) 对其无效 |
| \Z | 同 $,但 (?m) 对其无效 |
回溯引用
| 表达式 | 作用 |
|---|---|
| () | 括号内的作为一个子表达式,其中的元字符对应字符要匹配时需要转义,如”.” |
| \1 | \1、\2 等是回溯引用,\1 将回溯引用第一个子表达式,\2 回溯第二个,以此类推(\0 在多种语法中表示整个正则表达式) |
例如,使用回溯引用
1 | <[Hh]([1-6])>.*?</[Hh]\1> |
来匹配 html 1 到 6 级标题。
另外注意,使用
1 | .*? |
而不是
1 | .* |
是为了避免过度匹配,比如,使用
1 | <[Hh]([1-6])>.*</[Hh]\1> |
将在
1 | <h1>test1</h1><h2>test2</h1> |
中匹配到
1 | <h1>test1</h1><h2>test2</h1> |
前后查找
| 表达式 | 作用 |
|---|---|
| ?= | 向前查找,要作为子表达式使用 |
| ?<= | 向后查找,要作为子表达式使用 |
| ?! | 负向前查找,要作为子表达式使用 |
| ?<! | 负向后查找,要作为子表达式使用 |
例如,对于
1 | http://matian.connorma.cn |
使用向前匹配
1 | \w+(?=:) |
的匹配结果为
1 | http |
使用向后匹配
1 | (?<=://).* |
的匹配结果为
1 | matian.connorma.cn |
向前查找和向后查找可以起来,比如对上例,
1 | (?<=://)[\w\.]*(?=\.cn) |
将匹配到
1 | matian.connorma |
对于负向前/后查找,比如,
1 | 30 |
若要匹配所有金额数值,可以使用
1 | (?<=\$)\d+ |
将匹配到
1 | 59 |
若要匹配所有非金额的数字,可以使用
1 | \b(?<!\$)\d+\b |
将匹配到
1 | 30 |
这里要注意,如果不使用 \b,而使用如下的表达式
1 | (?<!\$)\d+ |
匹配结将是
1 | 30 |
条件(或)
对 OR 运算符“|”,
使用时注意
有优先级问题,如 19|20\d{2},匹配 19,或者 20xx 的四位数字;(19|20)\d{2},匹配 19xx 或者 20xx 的四位数字。
表现出短路,如 (((\d{1,2})|(1\d\d)|(2[0-4]\d)|(25[0-5])).){3}((\d{1,2})|(1\d\d)|(2[0-4]\d)|(25[0-5])) 意在匹配 ip 地址,但是好像,经测试,| 在正则表达式中,也表现出了短路的特性,会导致最后一段出现类似 255 只匹配到 25 的情况,而最后一段出现 256 时,将匹配到 25。\b(((\d{1,2})|(1\d\d)|(2[0-4]\d)|(25[0-5])).){3}((\d{1,2})|(1\d\d)|(2[0-4]\d)|(25[0-5]))\b 看起来更合理。
其他嵌入条件暂时没看。
常用表达式
匹配空白行(linux + windows)
1
[\r]?\n[\s]\*[\r]?\n
匹配 Email
1
(\w+\.)*\w*@(\w+\.)+[A-Za-z]+
匹配 URL 地址
1
[a-zA-z]+://[^\s]*
匹配 ip 地址
1
((?:(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d?\d))