在正则表达式里嵌入条件
顾名思义,我们可以在正则表达式里插入某些条件,这些条件可以作为另外一些正则表达式被执行的条件.
?:嵌入条件的语法使用?来定义,嵌入条件不外乎两种情况:
- 根据一个回溯引用来进行条件处理
- 根据一个前后查找来进行条件处理
回溯引用条件
回溯引用条件只在前一个子表达式成功匹配情况下才允许使用.回溯引用条件的语法是(?(backreference)true-regex).即如果回溯引用存在才指向后面的regex.
例子:
需要把一个文本里面的所有<IMG>标签找出来,如果某个标签是个链接(被包含在<a>和</a>之间),需要把整个链接标签匹配出来.
#
文本:
<a href=“/home”><img src=“/home/abc.png”></a>
<img src=“/Documents/cat.png”>
<H1>title something</H1>
<a href=“/home”><img src=“/home/ppl.png”></a>
<img src=“/Documents/dog.png”>
<H2>title haha something</H2>
正则表达式: (<[Aa]\s+[^>]+>\s*)?<[Ii][Mm][Gg]\s+[^>]+>(?(1)\s*</[Aa]>)
结果:
<a href=“/home”><img src=“/home/abc.png”></a>
<img src=“/Documents/cat.png”>
<a href=“/home”><img src=“/home/ppl.png”></a>
<img src=“/Documents/dog.png”>
这里的正则表达式第一部分是(<[Aa]\s+[\^>]+>\s*)?,它是一个子表达式用来匹配<a>或者<A>.第二部分\<[Ii][Mm][Gg]\s+[\^>]+>用来匹配一个(大小写均可).第三部分(
?(1)\s\*</[Aa]>)是一个回溯引用条件 — ?(1)的意思是如果第一个回溯引用存在,则使用\s\*</[Aa]>继续进行匹配.
回溯引用条件还有否定表达式,即在条件不满足的情况下才被执行,语法是(?(backreference)true-regex|false-regex)
#
文本:
123-456-2712
(123)442-9812
(123)-221-9123
(314-221-0812
1234567890
123 456 7890
正则表达式: (()?\d{3}(?(1))|–)\d{3}–\d{4}
结果: 123-456-2712 (123)442-9812
这个正则表达式分为几个部分,首先是(\()?用来匹配左括号,接着是d{3}匹配3个数字,然后是一个回溯引用条件(?(1)\)|-),它表示如果第一个回溯引用(左括号)存在,就执行\),即匹配右括号,如果不存在|就匹配破折号-.最后匹配3个和4个连续的数字.
前后查找条件
定义一个前后查找条件和回溯引用条件大同小异,只需要把回溯引用(括号里的回溯引用编号)替换为一个完整的前后查找表达式就行了.
#
文本:
11111
22222
33333-
44444-1123
正则表达式: \d{5}(-d{4})?
结果:
11111
22222
33333-
44444-1123
这并不是我们想要的效果,因为33333-被包含了进来.这时就是前后查找条件大显身手的时候.
#
文本:
11111
22222
33333-
44444-1123
正则表达式: \d{5}(?(?=–)-d{4})
结果:
11111
22222
44444-1123
\d{5}匹配前五个数字,接下来的(?(?=-)-d{4})使用了向前查找条件,它表示在-存在的情况下才继续向后匹配(匹配-\d{4}).这样就排除了33333-这种情况.