6.子表达式

正则表达式中的自表达式就是使用小括号对表达式进行分组归类等,如要匹配文本中的多个&nbps,使用&nbps{2,}会错误的匹配,只会匹配到多个s而不是&nbps,这里使用小括号将其包括起来:(&nbps){2,}就能成功匹配到多组给定字符集

  • ip地址

(\d{1,3}\.){3}\d{1,3}

  • 年份

(19|20)\d{2}

  • 使用子表达式的嵌套完善ip地址匹配

上面对ip的匹配依然有很多缺陷,如超过255的三位数字也会匹配进去,我们了解到一个ip地址组成每一段的数组需要满足以下条件

  1. 任意以1位或2位数字
  2. 任意以1开头的三位数字
  3. 任意以2开头、第二位在0-4之间的三位数字
  4. 任意以25开头,第三位在0-5之间的三位数字

(((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5]))\.){3}((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5]))

7.回溯引用

回溯引用允许正则表达式应用前面的匹配结果

  • 匹配连续两个相同的单词

[ ]+(\w+)[ ]+\1

这个表达式的回溯引用是末尾的\1,这里的\1表示的是第一个子表达式即前面小括号里面的匹配结果

  • 匹配html中的h1-h6标签

<[Hh]([1-6])>.*?</[Hh]\1>

这里使用回溯引用就不会错误地匹配到<h2></h3>中的内容

替换

...

8.前后查找

前面所述的正则匹配都是匹配指定满足的文本,而这里所使用的查找是匹配位于满足指定要求文本其相对位置的一段指定文本

向前查找

?=需要匹配的文本在后面,需要查找的文本在前面

  • 提取url中的协议名

.+(?=:)

向后查找

?<=

  • 提取$后的价格数字

(?<=\$)[\d.]+

前后查找组合

  • 匹配html标签<html></html>内的内容

(?>=<html>).*(?=</html>)

对前后查找取非

  • 向前查找与向前查找取非(即不与给定模式匹配的文本

    (?=),(?!)

  • 向后查找与向后查找取非

(?<=),(?<!)

9.嵌入条件

(?(back-reference)true-regex|false-regex)

用于判断给定的前面的回溯表达式是否有过成功匹配,若有则继续进行判断正确的匹配,若没有则进行另一种匹配

  • 提取img标签,若img标签被a标签包括,则一起提取出来

(<a\s+[^>]+>\s*)?<img\s+[^>]+>(?(1)\s*</a>)

(<a\s+[^>]+>\s*)这一段首先匹配a开始标签以及其属性,后方可以包含任意多个空白字符,后面加上?表示a标签也可以不存在;<img\s+[^>]+>用于匹配img标签以及其属性;(?(1)\s*</a>)最后这个模式开始的?(1)条件判断即判断以第一个模式是否有匹配成功,若找到匹配则继续进行后面的模式匹配\s*</a>以寻找a的关闭标签

  • 匹配北美电话号码格式

(\()?\d{3}(?(1)\)|-)\d{3}-\d{4}

123-456-7890

(123)456-7890

(123)-456-7890

(123-456-7890

1234567890

123 456 7890

对于前后查找的条件判断

前后查找条件只在一个向前或者向后查找操作匹成功时允许接下来的匹配,前后查找条件判断的使用与前面使用方法类似,只需要将?后面的回溯引用表达式替换为一个完整的前后查找表达式即可

  • 美国邮编匹配

美国的zip邮编有两种正确的格式1111111111-2222

\d{5}(?(?=-)-\d{4})

这里\d{5}首先匹配前五位数字,后面(?(?=-)-\d{4})中前面部分?(?=-)用于判断向后查找-是否成功找到,若找到则使用-\d{4}匹配后面一个dash加四位数字

11111

22222

33333-

44444-5555