跳到主要内容

9.2 向前查找

向前查找指定了一个必须匹配但不在结果中返回的模式。向前查找实际就是一个子表达式,而且从格式上看也确实如此。从语法上看,一个向前查找模式其实就是一个以 ?= 开头的子表达式,需要匹配的文本跟在=的后面。

提示 有些正则表达式文档使用术语“消费”(consume)来表述“匹配和返回文本”的含义。在向前查找里,被匹配的文本不包含在最终返回的匹配结果里,这被称为“不消费”。

我们来看一个例子。例子里的原始文本是一些 URL 地址,而你的任务是把它们的协议名部分提取出来(为下一步处理做准备)。下面就是这个例子:

.+(?=:)
在工具中查看
https://baidu.com
http://aliyun.com
https://qq.com

在上面列出的 URL 地址里,协议名与主机名之间以一个:分隔。模式.+匹配任意文本(第 1 个匹配是 http),子表达式 (?=:) 匹配:。注意,被匹配到的:并没有出现在最终的匹配结果里;我们用 ?= 向正则表达式引擎表明:只要找到:就行了,不要把它包括在最终的匹配结果里——用术语来说,就是“不消费”它。

为了更好地理解 ?= 的作用,我们再来看一个同样的例子,但这次不使用向前查找元字符:

.+(:)
在工具中查看
https://baidu.com
http://aliyun.com
https://qq.com

子表达式 (:) 正确地匹配到了: 并消费了这个字符——: 出现了最终的匹配结果。

这两个例子的区别是前一个用来匹配:的模式是 (?=:),后一个用来匹配:的模式是 (:)。这两个模式所匹配的东西是一样的——都是紧跟在协议名后面的那个:,它们之间的区别只是被匹配到的:字符有没有出现在最终的匹配结果里而已。在使用向前查找的时候,正则表达式分析器将向前查找并处理:匹配,但不会把它包括在最终的搜索结果里。模式 .+(:) 查找到并且匹配结果包含: 模式 .+(?=:) 查找到但匹配结果不包含。

注意

向前查找(和向后查找)匹配本身其实是有返回结果的,只是这个结果的字节长度永远是 0 而已。因此,前后查找操作有时也被称为零宽度(zero-width)匹配操作。

提示

任何一个子表达式都可以转换为一个向前查找表达式,只要给它加上一个 ?= 前缀即可。在同一个搜索模式里可以使用多个向前查找表达式,它们可以出现在模式里的任意位置(而不仅仅是出现在整个模式的开头——就像你们在上面看到的那样)。

该内容基于 《正则表达式必知必会》 二度创作
转载请遵守原作者相关协议并注明本页地址
https://iamhefang.cn/tutorials/正则表达式/第九章-前后查找/9.2-向前查找