在介绍完正则表达式的元字符、重复、分组的概念后,基本上我们对正则表达式的基本使用就OK了,本文我们讲一下正则表达式的高阶使用方式。
本节我们讲一下几种正则表达式的高级使用方式:
1. 正则表达式的后向引用 。
2. 零宽断言的概念及使用场景。
3. 负向零宽断言的概念及使用场景。
4. 冗长的平衡组合递归匹配。
一、后向引用
这里我们先举个例子,当我们需要匹配类似“taobao taobao”,“jingdong jingdong”这样的内容时,我们的正则表达式怎么写呢?
答: 可以使用 \b(\w+)\b\s+(\1) 来进行匹配。
下面解释一下具体的含义:这里 \b(\w+)\b 表示匹配的内容为字符串,(\1) 表示后向引用第1分组的内容进行匹配,所以,最终我们就能匹配到上面我们提到的场景的内容。
二、零宽断言
为什么会有零宽断言呢?是为了解决什么问题呢? 这个零宽断言的存在是为了解决我们一些特点的匹配要求,且不需要占位数。
零宽断言有正向、负向、先行、后行,一共有4种组合形式:
- (?=exp) 零宽正向先行断言: 匹配exp前面的位置
- (?<=exp) 零宽正向后行断言:匹配exp后面的位置
- (?!exp) 零宽负向先行断言: 匹配后面跟的不是exp的位置
- (?<!exp) 零宽负向后行断言:匹配前面不是exp的位置
下面可以结合一个例子对零宽断言进行理解:
三、平衡组递归匹配
这里我们先提出一个匹配特定内容的问题:如何把 xx <aa <bbb> <bbb> aa> yy 这样的字符里,最长的配对的尖括号内的内容捕获出来?
这里我们可以使用平衡组递归进行匹配,思路如下:
1. 我们可以使用 (?'group') 把捕获的内容命名为group,并压入堆栈(Stack)
2. 通过 (?'-group')从堆栈上弹出最后压入堆栈的名为group的捕获内容,如果堆栈本来为空,则本分组的匹配失败。
3. 通过(?(group)yes|no)来判断,如果堆栈上存在以名为group的捕获内容的话,继续匹配yes部分的表达式,否则继续匹配no部分。
需要注意的是:目前仅仅 .Net 支持平衡组递归匹配,其他语言例如Java、JavaScript 目前都不支持。这里我也就不过多的展开讨论和说明了。