一、回溯引用判断

到目前为止

1
2
3
"?(匹配前一个字符,或者表达式,如果存在的话)"
"?=(向前匹配,如果存在的话)"
"?<=(向后匹配,如果存在的话)"

条件语句:

1
(?(backreference)true-reges)

例一

目的

1
2
3
"需要把一段文本里的<IMG>标签全都找出来;不仅如此,如果某个<IMG>"
"标签是一个链接(被括在<A>和</A>标签之间)的话,你还要把整个链"
"接标签匹配出来。"

回溯引用条件语句

分析

1
2
3
4
5
1,所要匹配的文本中,<img></img>标签是无论如何都要求被匹配出的内容
2,<A></A>标签则成对出现,当且仅当有前者的时候,后者才可出现
3,因此条件语句的"backreferencr""(<[Aa]\s+[^>]+\s*)>",
"backreferencr"匹配<A>标签及其属性,
当且仅当它成功匹配时,其后的"true-regex""\s*\/[Aa]>"才回去匹配

注意

1
2
判断"backference"是否匹配成功的依据表达式(也就是回溯引用)
仅仅是指第几个子表达式(就是被括号包围住的式子)

(我的误区):

1
2
3
4
"认为第一个子表达式其后紧跟的?也属于判断表达式"
"然而事实上这个"?"只是为了在任何情况下"
"(即无所谓"backreference"是否有成功匹配)"
"它都会去执行后面<IMG>标签的匹配工作"

注意

1
2
3
"?(1)检查第一个回溯引用是否存在。在条件里,回溯引用编"
"号(本例中的1)不需要被转义。因此,?(1)是正确的,"
"?(\1)不正确(但后者通常也能工作)。"

例二:“(?(backer- ference)true-regex|false-regex)”的应用

目的:匹配北美电话号码

background:

1
2
3
4
(123)456-7890123-456-7890都是可接受的北美电话号码格式,
1234567890、(123)-456-7890和(123-456-7890)虽然都包含着数
目正确的数字字符,但它们的格式都不对。如果让你来编写一个正则表
达式并让它只匹配可接受的格式,不匹配其他格式,你会怎么做?

ture-regex_and_flase-regex

分析

1
2
3
4
"在此例中,可能会出现不同情况的符号组合为:"
"1,有"("的时候,则必有")",并且此时没有"-" "
"2,没有"("的时候,则必有"-",并且此时没有")" "
"因此被判断的回溯引用为:(\())"

二、前后查找条件

目的:

1
2
3
4
作为一个例子,请你思考一下怎样匹配美国的邮政编码(简称ZIP编
码)。美国邮政编码有两种格式,一种是12345形式的ZIP格式,另一
种是12345-6789形式的ZIP+4格式。只有ZIP+4格式才必须使用连字符
来分隔前5位和后4位数字。

分析

1
2
3
4
"此例中,前五位数字是必须的,"
"当且仅当五位数字其后紧跟着"-"的时候,"-"的后面才会有另外的四位数字"
"因此,变化的因素仅仅是"-\d{4}",或者说,只有在"-"之前存在合法的内容时"
"才会去匹配其后的内容"

例一

前后查找条件

思考(回溯引用条件与前后查找条件的特点)

1
2
"1,回溯引用条件更适合去判断更为具体的内容对文本的影响,因为其自身的表达式就是具体的匹配字句"
"2,而前后查找条件更适合去判断某几个特殊字符的位置,以及存在与否对整个文本内容的影响"

注意

1
2
3
4
前后查找条件只在一个向前查找或向后查找操作取得成功的情况下才允
许一个表达式被使用。定义一个前后查找条件的语法与定义一个回溯引
用条件的语法大同小异——只需把回溯引用(括号里的回溯引用编号)
替换为一个完整的前后查找表达式就行了