测试工具:regex101.com/ deerchao.cn/tools/weges…
正则表达式30分钟入门教程:deerchao.cn/tutorials/r…
十分钟快速掌握正则表达式:www.bilibili.com/video/BV1da…
一、限定符
(1)? 表示前面的字符只出现1次或者0次
// 表示 `d` 这个字符可有可无, 匹配结果为 use 或 used
used?
(2)*:表示前面的字符可以出现0~多次
// 表示 a 和 c 之间可以出现 0~n 个 b
ab*c
(3)+:匹配出现1次以上的字符
ab+c
(4){}:指定出现的次数,或范围
// 希望 b 出现6次
ab{6}c
// 希望 b 出现 [2,6] 之间
ab{2,6}c
// 希望 b 出现的次数在2次以上
ab{2,}c
注意:以上运算符如果想针对多个字符,可以使用括号把多个字符括起来。这些被括起来的被称为子表达式或分组
(ab)+c
(ab){6}c
二、或运算
匹配的字符串:
a cat
a dog
a bird
(1)匹配 a cat
或 a dog
,若都存在,则都匹配成功
// 注意 a 后面有空格,并且括号不能省略,否则匹配的将是 "a cat" 或者 "dog"
a (cat|dog)
(2)| 也可以用于分枝条件
正则表达式里的 分枝条件 指的是有几种规则,如果满足其中一种规则都应该当成匹配,具体方法是用 | 把不同的规则分隔开。
比如要匹配的邮编如下:
12345
12345-6789
可以使用 \d{5}-\d{4}|\d{5}
,这样上面的字符串都可以匹配成功,而如果改成 \d{5}|\d{5}-\d{4}
,那么只能匹配5位邮编,以及9位邮编的前5位。原因是匹配分枝条件时,将会从左到右地测试每个条件,如果满足了某个分支的话,就不会去再管其他条件了。
三、字符类
匹配的字符串
abc
tiger
aabbcc
dog
(1)方括号:[]
[abc]+
方括号里的内容代表要求匹配的字符只能取自于它们。
另外,我们可以在方括号里指定字符的范围:
// 下面的正则表达式代表所有的大小写字母和数字0~9
[a-zA-Z0-9]+
(2)脱字符:^
如果在方括号的前面我们写一个尖号(脱字符),则代表要求匹配除了尖号后面列出的 [以外] 的字符。
比如 [^0-9] 代表所有的非数字字符(包括换行符)。
四、元字符
- 数字字符:\d,相当于 [0-9]
- 单词字符:\w,包括英文字符、数字及下划线
- 空白符:\s,包含
Tab
和换行符 - 非数字字符:\D
- 非单词字符:\W
- 非空白字符:\S
- 任意字符,但不包含换行符:.(句点.)
\bword\b
:\b 标注字符的边界(全字匹配)- \B:匹配不是单词开头或结束的位置
- ^:匹配行首
// 只会匹配行首的 a
^a
- $:匹配行尾
// 只会匹配行尾的 a
a$
五、贪婪和懒惰匹配
当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符。以这个表达式为例:a.*b
,它将会匹配最长的以 a
开始,以 b
结束的字符串。如果用它来搜索 aabab
的话,它会匹配整个字符串 aabab
。这被称为贪婪匹配。
有时,我们更需要懒惰匹配,也就是匹配尽可能少的字符。前面给出的限定符都可以被转化为懒惰匹配模式,只要在它后面加上一个问号 ?
。这样 .*?
就意味着匹配任意数量的重复,但是在能使整个匹配成功的前提下使用最少的重复。现在看看懒惰版的例子吧:
a.*?b
匹配最短的,以 a
开始,以 b
结束的字符串。如果把它应用于 aabab
的话,它会匹配 aab
(第一到第三个字符)和 ab
(第四到第五个字符)。
匹配字符串
<span><b>This is a sample text</b></span>
上面说的 *+{}
在匹配字符串的时候,默认会匹配尽可能多的字符。即正则表达式默认使用贪婪匹配。
比如
// 会匹配到:<span><b>This is a sample text</b></span>
<.+>
把贪婪匹配改为懒惰匹配,只需要在右边加一个 ? 就好了
// 会匹配到 <span><b></b></span>
<.+?>
六、注释
小括号的另一个用途是通过语法 (?#comment) 来包含注释。
例如:
25[0-5](?#250-255)|2[0-4]\d(?#200-249)|[01]?\d\d?(?#0-199)
七、处理选项
上面介绍了几个选项如忽略大小写,处理多行等,这些选项能用来改变处理正则表达式的方式。下面是 .Net
中常用的正则表达式选项:
名称 | 说明 |
---|---|
IgnoreCase (忽略大小写) | 匹配时不区分大小写。 |
Multiline (多行模式) | 更改^和的精确含意是:匹配\n之前的位置以及字符串结束前的位置.) |
Singleline (单行模式) | 更改.的含义,使它与每一个字符匹配(包括换行符\n)。 |
IgnorePatternWhitespace (忽略空白) | 忽略表达式中的非转义空白并启用由#标记的注释。 |
ExplicitCapture (显式捕获) | 仅捕获已被显式命名的组。 |
一个经常被问到的问题是:是不是只能同时使用多行模式和单行模式中的一种?答案是:不是。这两个选项之间没有任何关系,除了它们的名字比较相似(以至于让人感到疑惑)以外。事实上,为了避免混淆,在最新的 JavaScript 中,单行模式其实名叫 dotAll
,意为点可以匹配所有字符,然而在指定该选项时,用的还是 Singleline
的首字母 s.
八、实例
1.RGB
颜色值匹配
要求:匹配所有十六进制的 RGB
颜色值。
#00
#ffffff
#ffaaff
#00hh00
#aabbcc
#000000
#ffffffff
正则表达式
// \b 表示边界,避免最后一个不符合要求的字符串,也被识别成 RGB 颜色值
[a-fA-f0-9]{6}\b
2.IPv4
地址匹配
123
255.255.255.0
192.168.0.1
0.0.0.0
256.1.1.1
This is a string
123.123.0
正则表达式
// \b 表示边界
\b((25[0-5]|2[0-4]\d|[01]?\d\d?).){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)\b
\