边界
位置匹配用来解决在什么位置进行匹配字符串的操作的问题,如我们想匹配到单词cat
匹配文本:The cat scattered his food all over the room.
正则表达式:cat
匹配到:The cat scattered his food all over the room.
我们只想匹配到单词cat而不想匹配到单词中的cat,这时候就需要用到边界来限制匹配内容的位置。
单词边界
第一种边界是由限定符\b指定的单词边界,\b用来匹配一个单词的开始或者结尾。
匹配文本:The cat scattered his food all over the room.
正则表达式:\bcat\b
匹配到:The cat scattered his food all over the room.
cat在句子中它前后都是空格,用\s(匹配一个空白字符)不也能达到同样效果吗?事实上如果用\scat\s我们是不能匹配到cat位于句子开头和结尾的情况,如:
匹配文本:cat eats cat and cat
正则表达式:\scat\s
匹配结果:cat eats cat and cat
因此,在匹配特定的单词时,最好使用\b作为单词边界。(说明:\b匹配的是这样的一个位置,这个位置位于一个能够构成单词的字符(\w匹配的字符)和不能构成单词的字符(\W匹配的字符)之间。其中b为boundary的首字母)
字符串边界
用来定义字符串边界的元字符有两个:^匹配字符串开头 $匹配字符串结尾
一般情况下,^将会匹配文本的开头,$将会匹配文本的结束位置。
说一般情况那是因为,在与(?m)一起使用时,表示匹配在一个换行处开头或者结束的字符串,如(?m)^,但许多正则表达式不支持(?m)
子表达式
子表达式是一个更大的表达式的一部分;把一个表达式划分为一些列子表达式的目的是把那些子表达式当作一个独立的元素来使用或者转换某种关系的先后顺序。子表达式必须用() 括起来。如果有需要子表达式允许嵌套。
例如我们想找到以19或者20开头的年份
年份:2008 1945 1644 1892 1946
正则表达式: (19|20)\d{2}
结果:2008 1945 1644 1892 1946
说明:|表示或.这里将19|20当作独立的表达式,如果不加括号,表达式会理解为19或20\d{2}
回溯引用:前后一致匹配
回溯引用指的是模式后半部分引用前半部分中定义的子表达式。
引例:
文本:<H1>This is valid HTML</H1> <H2>This is not valid HTML</H3>
正则表达式:<[hH][1-6].*?[hH][1-6]>
结果:<H1>This is valid HTML</H1> <H2>This is not valid HTML</H3>
对于这段html文本,第二句<H2></H3>是不合法的,但是采用上述正则表达式却把不合法的内容匹配到了,这是由于匹配的结束标签那部分对匹配开始标签那部分毫无所知。要解决这个问题,就要用到回溯引用。
解决:
正则表达式:<[hH]([1-6]).*?[hH]\1>
结果:<H1>This is valid HTML</H1> <H2>This is not valid HTML</H3>
这一次就很好的匹配到了合法的内容。注意到正则表达中,第一个[1-6]加了括号表示子表达式(如:<[hH]([1-6]).*?[hH]\1>),第二个[1-6]将其改成了\1(如:<[hH]([1-6]).*?[hH]\1>)。\1代表着模式里第1个子表达式(因此[1-6]加了括号)的重复出现1次,以此类推,\2表示第2个子表达式重复出现1次。需要说明的是不同正则表达式的回溯引用语法方面可能会有巨大差异。
前后查找
向前查找指定了一个必须匹配但不返回在结果中的模式。从语法上看,向前查找其实是一个?=开头的子表达式,需要匹配的文本跟在=后面;从形式上看,它是一个子表达式。
文本:
http://www.forta.com/
https://www.forta.com/
ftp://ftp.forta.com/
正则表达式:.+(?=:)
结果:
http://www.forta.com/
https://www.forta.com/
ftp://ftp.forta.com/
这样就可以提取出协议名而不带上:。
向后查找跟向前查找类似,但用的是?<=开头。但是有些语言的正则表达式不支持查找。
文本:
ABC01:$23.45
BEIXIFEN:$1000000
正则表达式:(?<=\$)[0-9.]+
结果:
ABC01:$23.45
BEIXIFEN:$1000000
向前向后查找可以结合起来,这样可以提取特定字符之间的内容;另外,前后查找可以取非(但不常用)。
(?=) 正向向前查找
(?!) 负向向前查找
(?<=) 正向向后查找
(?<!) 负向向后查找
附录 常见的正则表达式解决方案:
URL地址:https?://[-\w.]+(:\d+)?(/([\w/_.]*)?)?
完整的URL地址:https://(\w*:\w*@)?[-\w.]+(:\d+)?(/([\w/_.]*(\?\S+)?)?)?
电子邮件地址:(\w+\.)*\w+@(\w+\.)+[A-Za-z]+
HTML注释:<!-{2,}.*?-{2,}>
IP地址:(((\d{1,2})|(1\d{2})