跳到主要内容

9.3 向后查找

正如你刚看到的那样,?= 将向前查找(查找出现在被匹配文本之后的字符,但不消费那个字符)。因此,?= 被称为向前查找操作符。除了向前查找,许多正则表达式实现还支持向后查找,也就是查找出现在被匹配文本之前的字符(但不消费它),向后查找操作符是 ?<=

提示

分不清 ?=?<= 与其他 ? 的话,有个简单的办法可以帮你分辨它们:有小于号的是向后查找操作符——你可以把这个小于号想像成一个箭头,它指向文本阅读方向的后方。

?<=?= 的具体使用方法大同小异;它必须用在一个子表达式里,而且后跟要匹配的文本。

下面是一个例子。你有一份用户列表,但用户手机号前面是带有国家代码的,你需要把手机号分离搜索出来:

\+86\d{11}
在工具中查看
user1: +8613800000000
user2: +8613800000001
user3: +8613800000002
user4: +8613800000003
user5: +8613800000004
user6: +8613800000005

上面的模式已经把手机号成功的匹配出来,但如果你不想要要国家代码出现在结果里,该怎么办呢?直接把前面的 +86 去掉吗?

\d{11}
在工具中查看
user1: +8613800000000
user2: +8613800000001
user3: +8613800000002
user4: +8613800000003
user5: +8613800000004
user6: +8613800000005

这显然不是我们需要的结果。我们需要的是手机号但又不想要国家代码,这要怎么办呢?其实很好办,这正是向后查找可以大显身手的地方。

(?<=\+86)\d{11}
在工具中查看
user1: +8613800000000
user2: +8613800000001
user3: +8613800000002
user4: +8613800000003
user5: +8613800000004
user6: +8613800000005

这样问题就迎刃而解了。(?<=\+86) 匹配 "+86" 但不消费它,最终的结果里只有手机号而没有国家代码。

我们来对比一下这个例子的第一个和最后一个表达式:\+86\d{11} 匹配 "+86" 后面跟 11 位数字;(?<=\+86)\d{11}也是匹配 "+86" 后面跟 11 位数字。这两个模式查找的内容是一样的,它们之间的区间只体现在匹配的结果里面。前一个结果包含 "+86" 而后一个结果不包含。

警告

向前查找模式的长度是可变的,它们可以包含 .+ 之类的元字符,所以它们非常灵活。

而向后查找模式保能是固定长度——这是一条几乎所有的正则表达式实现都遵守的限制。

把向前向后查找结合起来

向前和向后查找并不是孤立存在的,它们可以结合起来使用,我们再来看一下 9.1 里面提出的例子:

(?<=<title>).*?(?=</title>)
在工具中查看
<head><title>何方的个人小站</title></head>

这样就可以解决只需要标题内容而不需要标题标签的问题了。

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