工具-正则表达式
参考文献
- 精通正则表达式第三版 Jeffrey E.F Friedl著
- 学习正则表达式 [美]Micbael Fitzgerald
校验网址
元字符
元字符 | 特殊含义 |
---|---|
. |
匹配除换行符以外的任意字符 |
^ |
匹配字符串的开始位置 |
$ |
匹配字符串的结束位置 |
* |
匹配前面的元素零次或多次 |
+ |
匹配前面的元素一次或多次 |
? |
匹配前面的元素零次或一次 |
\ |
转义字符,用于转义特殊字符 |
[] |
字符类,匹配方括号内的任意字符 |
() |
分组,用于捕获或分组匹配 |
{} |
限定符,指定匹配的次数 |
` | ` |
\d |
数字字符,等同于[0-9] |
\w |
单词字符,等同于[a-zA-Z0-9_] |
\s |
空白字符,包括空格、制表符、换行符等 |
\b |
单词边界,匹配单词的开始或结束位置 |
量词
量词 | 说明 |
---|---|
{n} |
在它之前的元素必须出现n次 |
{m,n} |
在它之前的元素最少出现m次,最多出现n次 |
{m,} |
在它之前的元素最少出现m次,出现次数无上限 |
{0,n} |
在它之前的元素,可以不出现,最多出现n次(在某些语言中可以写为{,n} ) |
常用量词
常用量词 | {m,n}等价形式 | 说明 |
---|---|---|
* |
{0,} |
可能出现,也可能不出现,出现次数没有上限 |
+ |
{1,} |
至少出现1次.出现次数没有上限 |
? |
{0,1} |
至多出现1次,也可能不出现 |
匹配优先量词与忽略优先量词
匹配优先量词 | 忽略优先量词 | 限定次数 |
---|---|---|
* | *? | 可能出现,也可能不出现,出现次数没有上限 |
+ | +? | 至少出现1次.出现次数没有上限 |
? | ?? | 至多出现1次,也可能不出现 |
{m,n} | {m,n}? | 在它之前的元素最少出现m次,最多出现n次 |
{m,} | {m,}? | 在它之前的元素最少出现m次,出现次数无上限 |
{,n} | {,n} | 在它之前的元素,可以不出现,最多出现n次( |
字符组[...]
匹配若干字符之一
1 | RE: gr[ae]y |
-
在字符组内部,字符组元字符
-
(连字符)表示一个范围1
[0-9a-zA-Z_!@#$%^&*()]
-
只有在字符组内部,连字符才是元字符,否则它就是匹配普通的连字符号
排除型字符组[^...]
- 这个字符组就会匹配任何未列出的字符,不是"不要匹配列出的字符"
- 在字符组外部,
^
表示一个行描点,但是在字符组内部(而且不行是紧接在字符组的第一个方括号之后),它就是一个元字符.
分组(...)
- 如果把一个表达式用括号包围起来,这个元素就是括号里的表达式,括号内的表达式通常被称为"子表达式"(
sub-expression
) - 括号的这种功能叫作分组(
grouping
).如果量词限定出现次数的元素不是字符或者字符组,而是连续的几个字符甚至是子表达式,就应该用括号将它们"编为一组". - 有了分组就可以准确表示"长度只能是m或n".
多选结构
- 多选结构的一般表示法是
(option1|option2)
其中option1
和option2
是两个作为多选分值的正则表达式.在多选结构中一般会同时使用括号()
和竖线|
;但是如果没有括号,只出现竖线|
,仍然为多选结构.- 在多选结构中,竖线
|
用来来分隔多选结构,而括号用来规定整个多选结构的范围,如果没有出现括号,则将整个表达式视为一个多选结构,所以ab|cd
等价与(ab|cd)
.
- 在多选结构中,竖线
- 多选分支不等于字符组.多选分支看起来类似字符组,如
[abc]
能匹配的字符串和(a|b|c)
一样,[0-9]
能匹配的字符串和(0|1|2|3|4|5|6|7|8|9)
一样.从理论上说,可能完全用多选结构来替换字符组,但这种做法不推荐,理由在于:首先,[abc]
比(a|b|c)
要简洁许多,在多选结构中的每个分支都必须明确写出,不能使用-
范围表示法. - 多选分支和字符组的另一个重要区别:排除性字符组可以表示"无法由某几个字符匹配的字符",多选结构却没有对应的结构表示"无法由某几个表达式匹配的字符串".
- 注意: 如果出现多选结构应当尽量避免多选分支中存在重复匹配,因为这样会大大增加回溯的计算量.也就是说,应当避免这样的情况: 针对多选结构
(option1|option2)
,某段文本既可以由option1
匹配,也可以由option2
匹配.如果出现了这样的多选结构,效率可能收到极大的影响.
引用分组
-
括号不仅能把有联系的元素聚拢起来并分组,还有其他的作用–使用括号之后,正则表达式会保存每个分组真正匹配的文本,等匹配完成之后,通过
group(num)
之类的方法"引用"分组在匹配时捕获的内容.- 其中
num
表示对应括号的编号,括号分组的编号规则是从左向右计数,从1开始.因为捕获了文本,所以这种功能叫作捕获分组(captureing group
).对应的,这种括号叫作捕获型括号 - 也有编号为0的分组,它是默认存在的,对应整个表达式匹配的文本
1
2
3
4
5
6字符串: 2010 - 12 - 22
字符串: 2010 - 12 - 22
表达式: (\d{4]})-(\d{2]})-(\d{2]})
分组编号: 1 2 3 - 其中
-
一般来说,正则表达式匹配完成之后,会得到一个表示"匹配结果"的对象,对它调用获取分组的方法,传入分组编号
num
,就可以获得对应分组匹配的文本.
反向引用(back-reference
)
- 它允许在正则表达式内部引用之前的捕获分组匹配的文本(也就是左侧),其形式也是
\num
,其中num
表示所引用分组的编号. - 根据反向引用,查找连续重叠字母的表达式就是
([[a-z]]\1)
,其中的[a-z]
匹配的第一个字母,再用括号将匹配分组,然后用\1
来反向引用. - 反向引用重复的对应捕获分组匹配的文本,而不是之前的表达式,即反向引用是一种"引用",对应的是由之前表达式决定的具体文本,它本身并不规定文本的特征.
非捕获分组(no-capturing-group
)
- 非捕获分组类似普通的捕获分组,只是在开括号后紧跟一个问号和冒号
(?:...)
,这样的括号叫作非捕获型括号,它只能限定量词的作用范围,不捕获任何文本. - 分组的编号同样会按开括号出现的顺序从左到右递增,只是必须以捕获分组为准,会略过非捕获分组.
断言(assertion
)
- 正则表达式中大多数据结构匹配的文本会出现在最终的匹配结果中(一般用
group(0)
可以得到),但是也有些结构并不真正匹配文本,而只负责判断某个位置左/右侧的文本是否符合要求,这种结构被称为断言. - 常见的断言有三类:
- 单词边界
- 行起始/结束位置
- 环视
单词边界
- 使用
\b
表示单词边界
字符串 | \brow\b |
\brow |
row\b |
---|---|---|---|
tomorrow |
√ | ||
brown |
|||
row |
√ | √ | √ |
rowdy |
√ | ||
表达式说明 | 只能是单词row | \b的右侧是单词字符,所以左侧不能是个单词字符 | \b的左侧是单词字符,所以右侧不能是个单词字符 |
- 单词边界不区分左右
- 单词字符要求"另一边不是单词字符",而不是"另一边的字符不是单词字符",即一边必须是单词字符,另一边可以出现非单词字符,也可能没有任何字符.
行起始/结束位置
- 单词边界匹配的是某个位置而不是文本,在正则表达式中,这类匹配位置的元素叫作锚点(
anchor
),它用来定位到某个位置. - 常用的锚点除了
\b
,还有^
和$
分别表示匹配字符串的开始位置和结束位置 - 多行模式最简单的办法是在正则表达式之前加上
(?m)
环视
名字 | 记法 | 判断方向 | 结构内表达式匹配成功的返回值 |
---|---|---|---|
肯定顺序环视 | (?=...) |
向右 | True |
否定顺序环视 | (?!...) |
向右 | False |
肯定逆序环视 | (?<=...) |
向左 | True |
否定逆序环视 | (?<!...) |
向左 | False |
-
否定的意思是: “如果正则表达式匹配成功,则在当前位置匹配失败”
-
顺序和逆序则表示正则表达式需要匹配的文本所在位置.
-
记忆方式: 在当前位置,如果是朝右判断,则是顺序环视(
lookhead
),如果是朝左判断,则是逆序环视(lookbehind
);如果要求子表达式能匹配的字符串必须出现,则肯定环视(positive
),如果要求子表达式能匹配的字符串不能出现,则为否定环视(negative
). -
示例,对于字符串
12345
,以\d{3}
为表示式的四种环视能匹配的位置分别是:- 右侧必须出现三个数字字符
- 右侧不能出现三个数字字符
- 左侧必须出现三个数字字符
- 左侧不能出现三个数字字符
1
2
3
4
51 2 3 4 5
(?=\d{3}) ↑ ↑ ↑
(?!\d{3}) ↑ ↑ ↑
(?<=\d{3}) ↑ ↑ ↑
(?<!\d{3}) ↑ ↑ ↑ -
环视的最大特点是:“匹配完成之后还停在原地”
匹配模式(match mode
)
- 匹配模式指的是匹配时遵循的规则.
- 常用的匹配模式一共有四种:
- 不区分大小写模式
- 单行模式
- 多行模式
- 注解模式
不区分大小写模式
- 模式的指定方式,通常有两种办法指定匹配的模式:
- 以模式修饰符指定
- 模式修饰符即模式名称对应的单个字符,使用时将其填入特定结构
(?modifier)
中(其中的modifier
为模式修饰符),嵌在正则表达式的开头.比如不区分大小写的匹配模式的对应模式修饰符为i
,对the
指定此模式,完整的正则表达式就是(?i)the
- 这种表达式几乎可以原封不动地在任何语言中使用,其意义都是相同的.
- 模式修饰符即模式名称对应的单个字符,使用时将其填入特定结构
- 以预定义的常量作为特殊参数传入来指定
- 以模式修饰符指定
- 不区分大小写的匹配模式的对应模式修饰符为
i
(case Insensitive
),表达式为(?i)
单行模式
- 元字符点号
.
几乎能匹配任何字符,唯有换行符\n
是例外的. - 单行模式对应的模式修饰符是
s
(Single line
),表达式为(?s)
多行模式
- 多行模式对应的模式修饰符是
m
(Multiline
),表达式为(?m)
注释模式
-
(?#comment)
1
^(?#start of the line)\d(?#digit).*(?#rest of the line)
转义
元字符的转义
结构 | 记法 | 转义 | 说明 |
---|---|---|---|
字符组 | [] |
\[] |
只对开括号转义 |
字符组 | . |
\. |
|
字符组 | - |
\- |
[a\-b]等价与[-ab] |
量词 | * + ? |
\* \+ \? |
|
量词 | *? +? ?? |
\*\? \+\? \?\? |
|
量词 | {m,n} |
\{m,n} |
只对开花括号转义 |
括号 | (...) |
\(...\) |
开闭括号都要转义 |
多选结构 | ` | ` | | |
括号和多选结构 | `(… | …)` | \(...|...\) |
断言 | ^ $ |
\^ \$ |
|
替换引用 | $num |
\$ 或$$ |
在替换的replacement 字符串中转义 |
常用示例
身份证
1 | ^[1-9]\d{14}(\d{2}[0-9x])?$ |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 HoleLin's Blog!