正则表达式反向引用,子表达式重要用途在于恰当地控制重复的匹配模式,本文介绍子表达式的一种重要用途-反向引用(backreference)。
为什么需要反向引用
要理解为什么需要反向引用,最好的方法是看一个例子。HTML 程序员使用标题标签(<h1>
到<h6>
,以及配对的结束标签)来定义和排版 Web 页面里的标题文字。假设你现在需要把某个 Web 页面的所有标题文字全部查找出来,不管是几级标题。如下所示:
文本
<body>
<h1>Welcome to my Homepage</h1>
Content is divided into two sections:<br/>
<h2>SQL</h2>
Information about SQL.
<h2>RegEx</h2>
Information about Regular Expressions.
</body>
正则表达式
<[hH][1-6]>.*?<\/[hH][1-6]>
执行结果
看起来没有问题,可是真的是这样的吗?未必哟,看看下面这个例子。
文本
<body>
<h1>Welcome to my Homepage</h1>
Content is divided into two sections:<br/>
<h2>SQL</h2>
Information about SQL.
<h2>RegEx</h2>
Information about Regular Expressions.
<h2>This is not valid HTML</h3>
</body>
正则表达式
<[hH][1-6]>.*?<\/[hH][1-6]>
执行结果
我们发现有一处标题的标签是以<h2>
开头,以</h3>
结束,这显然是个无效的标题,但是也能和我们使用的模式匹配上,问题在于匹配的第二部分对匹配的第一部分一无所知。这个时候,就需要反向引用闪亮登场了!!!!
反向引用匹配
解决匹配 HTML 标题的问题前,我们先看一个简单例子,如果不使用反向引用,根本无法解决。
假设你有一段文本,你想把这段文本里所有连续重复复现两次的单词打印出来,显然再搜索某个单词的第二次出现时,这个单词必须是已知的。反向引用允许正则表达式模式引用之前匹配的结果。如下所示:
文本
This is a block of of text.
several words here are are
repeated, and and they
should not be.
正则表达式
[ ](\w+)[ ]\1
执行结果
注意,\w+
是出现在括号里,所以它是一个子表达式,该子表达式对模式进行分组,将其标识出来以备候用。模式最后一部分是\1
,这是对前面那个子表达式的反向引用,\1
匹配的内容与第一个分组匹配的内容一样。如果(\w+)
匹配的单词是of
,那么\1
也匹配 of。
\1
到底是什么意思呢?它匹配模式中所使用的第一个子表达式,\2
匹配第二个子表达式,\3
匹配第三个,以此类推。
了解反向引用的用法之后,再回到 HTML 标题的例子,利用反向引用可以构造一个模式去匹配任何标题的开始标签和相应的结束标签。如下所示:
文本
<body>
<h1>Welcome to my Homepage</h1>
Content is divided into two sections:<br/>
<h2>SQL</h2>
Information about SQL.
<h2>RegEx</h2>
Information about Regular Expressions.
</body>
正则表达式
<([hH][1-6])>.*?<\/\1>
执行结果
反向引用基本原理是:捕获组匹配成功时,会将子表达式匹配到的内容,保存到内存中一个以数字编号的组里,可以简单的认为是对一个局部变量进行了赋值,这时就可以通过反向引用方式,引用这个局部变量的值。捕获组在匹配成功之前,它的内容可以是不确定的,一旦匹配成功,它的内容就确定了,反向引用的内容也就是确定的了。
极客教程相关文章推荐,欢迎阅读!
正则表达式子表达式
正则表达式匹配数字范围
正则表达式回溯法
正则表达式位置匹配
正则表达式重复匹配
正则表达式排除字符
正则表达式元字符