正则表达式前后查找,本文介绍正向前查找,负向前查找,正向后查找和负向后查找。各种前后查找操作符如下表所示:
操作符 | 说明 |
---|---|
(?=) |
正向前查找 |
(?!) |
负向前查找 |
(?<=) |
正向后查找 |
(?<!) |
负向后查找 |
向前查找
向前查找指定了一个必须匹配但不在结果中返回的模式。向前查找实际就是一个子表达式,而且从格式上看也确实如此。从语法上看,一个向前查找模式其实就是一个以 ?=
开头的子表达式,需要匹配的文本跟在 = 的后面。
有些正则表达式文档使用术语 “消费”(consume) 来表述 “匹配和返回文本” 的含义。在向前查找里,被匹配的文本不包括在最终返回的匹配结果里,这被称为 “不消费”。
下面的例子是将一些 URL 地址的协议名部分提取出来。
文本:
http://www.forta.com/
https://mail.forta.com/
ftp://ftp.forta.com/
执行正则表达式:
.+(?=:)
执行结果:
在上面列出的 URL 地址里,协议名与主机名之间以一个 : 分隔。模式 .+
匹配任意文本(第1个匹配是 http),子表达式 (?=:)
匹配 : 。注意,被匹配到的 : 并没有出现在最终的匹配结果里,我们用 ?=
向正则表达式引擎表明只要找到 : 就行了,不要把它包括在最终的匹配结果里,用术语来说,就是 “不消费” 它。
向前查找(和向后查找)匹配本身其实是有返回结果的,只是这个结果的字节长度永远是 0 而已。因此,前后查找操作有时也被称为零宽度匹配操作。
任何一个子表达式都可以转换为一个向前查找表达式,只要给它加上一个 ?=
前缀即可。在同一个搜索模式里可以使用多个向前查找表达式,它们可以出现在模式里的任意位置。
向后查找
除了向前查找,许多正则表达式实现还支持向后查找,比如:Java、.NET、PHP 和 Perl 都支持向后查找(但有一些限制),但是JavaScript 和 ColdFusion 不支持向后查找。向后查找也就是查找出现在被匹配文本之前的字符(但不消费它),向后查找操作符是 ?<=
。
?<=
与 ?=
的具体使用方法大同小异,它必须用在一个子表达式里,而且后面跟要匹配的文本。
文本:
http://www.forta.com/
https://mail.forta.com/
ftp://ftp.forta.com/
执行正则表达式:
(?<=://).+
执行结果:
向前查找模式的长度是可变的,它们可以包含 . 和 + 之类的元字符,而向后查找模式只能是固定长度,这是一条几乎所有的正则表达式实现都遵守的限制。
结合向前查找和向后查找
文本:
<head>
<title>my homepage</title>
</head>
执行正则表达式:
(?<=<[Tt][Ii][Tt][Ll][Ee]>).*(?=</[Tt][Ii][Tt][Ll][Ee]>)
执行结果:
前后查找取非
前面结束的向前查找和向后查找被称为正向前查找和正向后查找,术语“正”指的的寻找匹配的事实。前后查找还有一种不太常见的用法叫做负前后查找。负向前查找将向前查找不与给定模式相匹配的文本,负向后查找将向后查找不与给定模式向匹配的文本。
一般来说,凡是支持向前查找的正则表达式实现都同时支持正向前查找和负向前查找。类似地,凡是支持向后查找的正则表达式实现都同时支持正向后查找和负向后查找。
文本:
I paid $30 for 100 apples
执行正则表达式:
(?<=\$)\d+
结果:
文本:
I paid $30 for 100 apples
执行正则表达式:
\b(?<!\$)\d+\b
执行结果:
极客教程相关文章推荐,欢迎阅读!
正则表达式回溯法
正则表达式位置匹配
正则表达式重复匹配
正则表达式排除字符
正则表达式 – 元字符