文章目录
我们在使用正则表达式时有时需要确定上界或者下界,我们需要他后面或者前面的内容,而这个边界我却不需要。这时候我们就需要“环视”,环视能够向前或者向后查看,环视可以去除一些不用被返回的匹配。
所有的主流的正则表达式实现都支持前者,但支持后者的就没那么多了。Java、.NET、PHP、Python 和 Perl 都支持向后查看(其中一些有限制),JavaScript 则不支持。
向前查看
向前查看指定了一个必须匹配但不用在结果中返回的模式。向前查看其实就是一个子表达式,而且从格式上看也确实如此。向前查看模式的语法是一个以 ?=
开头的子表达式,需要匹配的文本跟在 =
的后面。
匹配模式:
.+(?=66)
匹配字符:qw6
qwjy
qw66
模式 .+
匹配任意文本(匹配是 qw),子表达式 (?=66)
匹配。注意,被匹配到的 66 被没有出现在最终的匹配结果里。?=
告诉正则表达式引擎:匹配 : 只是为了向前查看(不用消耗该字符)。
我们再看一个例子。
匹配模式:
.+(66)
匹配字符:qw6
qwjy
qw66
子表达式 (66)
正确匹配并消耗了 66
,该字符被作为最终匹配结果的一部分返回。
这两个例子的区别在于,匹配 66
的时候前者使用的模式是 (?=66)
,而后者使用的模式是 (66)
。两种模式匹配到的东西是一样的,都是紧跟在名称后面的那个 66
,不同之处是匹配到的 66 是否出现在最终的匹配结果之中。
向前查看和向后查看其实是有返回结果的,只不过结果永远都是零长度字符串。因此,环视操作有时也被称为零宽度匹配操作。
任何子表达式都可以转换为向前查看表达式,只要在其之前加上一个 ?=
即可。 在同一个搜索模式里可以使用多个向前查看表达式,出现的位置没有任何限制。
向后查看
向后查看操作符是 ?<=
。
?<= 的用法与 ?= 一样。它必须出现在一个子表达式里,后面跟随要匹配的文本。
匹配模式:
(?<=go).+
匹配字符:66qw
ccqw
goqw
向前查看模式的长度是可变的,其中可以包含 . 和 + 等量词,所以非常灵活。
向后查看模式则只能是固定长度。几乎所有的正则表达式实现都是此限制。
结合向前查看和向后查看
向前查看和向后查看可以结合在一起使用。
匹配模式:
(?<=go).+(?=cc)
匹配字符:go qw
qw cc
go qw cc
否定式环视
种类 | 说明 |
---|---|
(?=) |
肯定式向前查看 |
(?!) |
否定式向前查看 |
(?<=) |
肯定式向前查看 |
(?<!) |
否定式向后查看 |
一般来说,凡是支持向前查看的正则表达式实现也都支持肯定式向前查看和否定式向前查看。类似地,凡是支持向后查看的正则表达式实现也都支持肯定式向后查看和否定式向后查看。
匹配模式:
(?<!go)qw(?!cc)
匹配字符:go qw
qw cc
goqwcc