js正则表达式

本文主要记录js正则表达式中的难点:惰性匹配,贪婪匹配,分组组合,反向引用符。

贪婪匹配与非贪婪匹配

贪婪与非贪婪模式影响的是被量词修饰的子表达式的匹配行为,贪婪模式在整个表达式匹配成功的前提下,尽可能多的匹配,
而非贪婪模式在整个表达式匹配成功的前提下,尽可能少的匹配。非贪婪模式只被部分NFA引擎所支持。

贪婪匹配

默认情况下,正则表达式使用最长的匹配原则,即贪婪匹配原则。
举个例子:

1
2
3
源字符串:aa <div>test1</div> bb <div>test2</div>cc
贪婪模式的正则表达式:<div>.*</div>
匹配结果:<div>test1</div>bb<div>test2</div>

这就是贪婪匹配的结果,当第一个div结束后,依旧会向右匹配直到字符串结束。
仅从应用角度分析,可以这样认为,贪婪模式,就是在整个表达式匹配成功的前提下,尽可能多的匹配,也就是所谓的“贪婪”,通俗点讲,就是看到想要的,有多少就捡多少,除非再也没有想要的了。

惰性匹配

在一些使用NFA引擎的语言中,在匹配优先量词后加上“?”,即变成属于非贪婪模式的量词,也叫做忽略优先量词。

1
2
3
源字符串:aa <div>test1</div> bb <div>test2</div>cc
惰性模式的正则表达式:<div>.*</div>
匹配结果:<div>test1</div>

当表达式匹配成功后,即结束匹配,不再向右尝试。
仅从应用角度分析,可以这样认为,非贪婪模式,就是在整个表达式匹配成功的前提下,尽可能少的匹配,也就是所谓的“非贪婪”,通俗点讲,就是找到一个想要的捡起来就行了,至于还有没有没捡的就不管了。
当然这一切的前提是”匹配成功”

分组组合符与反向引用符

分组组合符是将表达式中某部分内容组合起来的符号,反向引用符则是用于匹配分组组合捕获到的内容的标识符。
在正则表达式中,可以用一对(英文)圆括号创建一个分组。比如([a-z]+)(/d+)这就是两个分组。
分组的作用表现在两个方面,一个是同一模式后续的组件中,称之为反向引用(back_reference),二是替换模式中引用,称之为编号组。

反向引用

将第一个模式修改为([a-z]+)(/d+)/1之后现在就能够匹配ABC123ABC,A8A等等类似的字符串。这个修正模式后的/1就叫做方向引用,数字1表示引用模式中的第一个捕获组。
再来一个例子:\w\w可以匹配”ac,bd,ef”等等,但是\w/1就只能匹配”aa,cc,dd,ee”等相同的字符,这个反向引用匹配的字符与捕获组是一致的。
实际应用比如标签符<(h[1-6])>/w+<//1>这样就可以匹配h1到h6的标签符了。如果不反向引用就可以导致不对称的标签符,而反向引用是一致的。

替换模式

编号组的概念也是建立在匹配模式中的分组之上的。它与反向引用的区别在于,编号组是在替换模式中使用的一个概念。
例子:([A-Z]{3})(/d{2})为例,该模式匹配ABC12,CDS56等3个字母2个数字的的字符序列。如果要在字母和数字间插入一个空格或者连字符作为分隔符,就可以在替换模式中使用编号组,比如:
$1-$2,其中$1就是([A-Z]{3}),$2就是(/d{2}),连字符就是-。这样就完成了需要的功能。
$1就相当于那一整个编号组。

小结

有时候也将在替换模式中使用的编号组称为反向引用。所以,可以认为无论是/1还是$1还是${date},只是因地制宜地使用了不同的形式而已,在本质上它们都是反向引用。

总结

一遍又一遍的学习正则表达式,这些难点总是使用时候就忘了,忘了又看。一直没有总结下,这一次重新学习基础,就总结一下这非常重要的正则表达式吧。