之前使用正则表达式,总对一部分正则语法模棱两可。这周末看了《正则表达式必知必会》,一本100来页的小工具书,非常实用,系统地梳理了正则表达式的语法。本文主要围绕这本书,从易到难介绍正则的使用,用于帮我自己梳理思路。

匹配单个字符

1、直接某个字符匹配该字符

2、使用.匹配任意一个字符

3、使用\匹配元字符,比如\.\\

匹配一组字符

1、在[]中放置一个字符集合,匹配其中的一个,比如[ns],匹配n或者s

2、在[]中放置一个范围,匹配其中的一个,比如[A-Za-z0-9],匹配数字或者字母

3、在[]中可以使用取非操作,比如[^0-9],表示非数字字符

使用元字符

1、可以通过增加\来匹配元字符,比如\[\]\.\\

2、匹配空白字符,即匹配各种控制字符,比如换行(\n),回车(\r)、换页(\f),制表符(\t),垂直制表(\v)等。比较常见是使用\r\n匹配windows系统的换行,Linux系统的换行是\n

3、匹配字符类别

元字符 匹配说明
\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]
POSIX字符集 比如[[:xdigit:]]匹配十六进制数字

重复匹配

1、重复规则

规则 匹配说明
+ 一个或多个,比如\w+,表示至少一个字母数字下划线类型字符
* 零个或多个
? 零个或一个
{3} 指定个数 (注意,这里的数字只是举例,下面出现的集合例子也用一个数字举例)
{3,5} 指定区间,可以是开区间,比如{3, },表示大于等于3

2、贪婪型和懒惰型

重复匹配中的+*{a,}(注意,是开区间),这三个模式都没有一个上限值,所以存在贪婪行为和懒惰行为的区分,默认都是贪婪行为。
二者的区别在于,贪婪行为会尽可能的匹配最长的结果,而懒惰行为则会尽量匹配最小的结果。

为了将以上三种重复匹配切换为懒惰模式,需要做相应转换。

贪婪 懒惰
+ +?
* *?
{3,} {3,}?

位置匹配

1、单词边界,可以使用\bcat\b这样的模式,匹配单词cat,匹配到的字符串必须是一个独立的单词,也就是两侧都是空格,而不能是某个单词的一部分。顾名思义,\bcat和’cat\b’分别表示以’cat’开头和结尾的单词。

2、非单词边界,使用\B-\B将会匹配on your color - coded中的-。(这个用法我还存在疑问)

3、字符串开头匹配,在正则开头加上^,字符串结尾匹配,在正则表达式末尾加上^.*$可以表示任意字符。

4、分行匹配,在模式开头启用(?m)将会使得^$以行为单位进行处理。

子表达式

前面我们学习的匹配字符多次重复的语法,都是针对单个字符的重复,而子表达式是为了处理多个字符的重复,多个字符组成一个子表达式。只需用()包围起来即可成为一个子表达式,包围的内容可以是一个普通字符串,也可以是一个正则表达式。

子表达式除了用于表达字符串的重复,还用于|操作符两侧的条件做出准确的定义,最好对复杂的条件使用子表达式

另外,子表达式支持嵌套使用。

回溯引用:前后一致匹配

可以使用\1\2\3这样的格式,代表一个正则表达式中的第一,二,三个子表达式,这就是回溯引用的意思。

比如以下例子

1
<[hH]([1-6])>.*?</[Hh]\1>

回溯引用

以上例子,会匹配到所有正确的HTML的标题标签,而不会匹配到最后一行错误的<H2>This is not valid line</H3>

回溯引用除了用于文本匹配,也可以用于文本替换,关于文本替换,这里就不列举了,推荐参考原书。

前后查找

前后查找是指对某一些位置的前后进行查找,比如,查找html中<Title></Title>中间的标题内容,而且匹配结果不带上<Title></Title>标签。

向前匹配,使用(?=),比如

1
.*(?=:)

向前查找

向后匹配,使用(?<=),比如

1
(?<=\$)[0-9.]+

向后查找

向前查找和向后查找可以结合使用,这个用法用法在解析HTML时很使用,比如提取<Title></Title>中间的内容。

向前查找和向后查找也可以取非,意义在于,不用特定字符开始或不用特定字符结尾,同样的,这些特定字符不在最终匹配结果中。向前查找取非:(?!),向后查找取非:(?<!)

嵌入条件

嵌入条件用于两种地方,回溯引用和前后查找。

以下是回溯引用嵌入条件的一个例子

1
(\()?\d{3}(?(1)\)|-)\d{3}-\d{4}

回溯引用的嵌入条件

其中精华在于这一段,(?(1)xx|yy),如果回溯引用1成立,则执行xx匹配,否则执行yy匹配

以下是前后查找嵌入条件的一个例子,

1
\d{5}(?(?=-)-\d{4})

前后查找的嵌入条件

如果向前查找(?=-)成立,则需要继续匹配-\d{4}

书的末尾,提到了各个语言的正则表达式解析引擎存在一些大大小小的区别。

最后,推荐一个在线正则匹配的网站,https://regex101.com/

好,到此为止,介绍忘了正则的基本语法,下一节会介绍正则的解析引擎,DFA和NFA,敬请期待。