`

正则表达式中的LookAround

 
阅读更多

这个东东有人把他直译为环视,到也还算贴切。因为本来这东西就分为head和behind两种类型。

分别表示找前面的和找后面的部分。然后又根据是想匹配括号里的内容还是不想匹配括号里的内容,分为了Positive和Negative两种。这样你就会发现目前已经分别在两个维度上有了分别两种分法,于是这就组合出了LookAround的全部四种情况:

  • Positive Lookahead
  • Negative Lookahead
  • Positive Lookbehind
  • Negative Lookhehind

看了上面说的东西,我自己都觉得晦涩,还是得上例子。

假设我一个文件,里面有N多的abc-123-efg这种形式的字符串,如果我想取出这种形式的字符串中的数字怎么办?(就是上面例子中的123).

一种最直观的想法是使用分组,也是正则中比较常用的手段,比如下面的perl code(如果你希望运行下面的code请确保你的PATH中有perl)

perl -e ' "abc-123-efg" =~ /\w+-(\d+)-\w+/; print "Total matched : $& and group 1 is : $1\n"; '
##########print on the console###########
# Total matched : abc-123-efg and group 1 is : 123

 从上面的语句和运行结果看,我们可以拿到123,但是显然123是分组1的匹配,并不是整个pattern的匹配,整个pattern的匹配是整个这个字符串本身。也就是说上面数字的截取是通过正则的分组机制绕了个弯执行的。

这有啥不好的?其实这也没啥不好,管他黑猫白猫,能抓耗子就是好猫。不过有时你可能会遇到一些场景希望一次性的把你需要的匹配直接反应到匹配结果上,比如:你用某些文本编辑器打开了上面的文件,像利用文本编辑器提供的正则表达式的地方,把上面的123这种数字一下子全匹配到,通常这之后编辑器一般也会给你高亮显示匹配的结果。

总之,类似于这样的场景下,LookAround就有登场的必要了。

下面的例子使用了Positive的lookbehind和lookahead:

perl -e ' "abc-123-efg" =~ /(?<=\w{3}-)\d+(?=-\w+)/; print "Total matched : $& and group 1 is : $1\n"; '
##########print on the console############
# Total matched : 123 and group 1 is :

 请注意以上pattern和上一个例子的比较,\d+已经不在分组中,取而代之的是他前面使用了一个positive lookbehind,后面使用了一个positive lookahead。从这个例子中你应该可以体会到,positive其实是需要匹配,但是匹配了之后并不将这个匹配放入最后的匹配结果,而是将这部分之后(look behind)或者之前(look ahead)的部分放入匹配结果。

如果你足够细心的话,会发现上面的look behind和look ahead中pattern的量词不一样,一个是固定数量的3,一个是不限定数量的+,这里其实并不是因为我们业务上数字前面的字符串的长度一定是3,而是因为我本机perl 5.12的测试结果显示perl5.12还不支持在lookbehind中使用使用不定长度的量词,如果写成和lookahead一样的话,会得到下面的错误:

Variable length lookbehind not implemented in regex m/(?<=\w+-)\d+(?=-\w+)/ at -e line 1.

 好了,上面举了一个简单的positive lookbehind和lookahead的例子,还剩下两个negative lookhebind和lookahead的没说,这个跟positive最大的区别,相信你从名字上也能猜出个一二了,就是不匹配那块的东西。艾,说起来也真拗口。具体的还是看人家老外写的例子吧,这篇文章写的非常详细,值得细读。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics