在字符模式中,后面的字符可以引用前面的子表达式。实现方法:
\ + 数字
数字指定了子表达式在字符模式中的顺序。如“\1”引用的是第1个子表达式,“\2”引用的是第2个子表达式。
【示例1】在上下面代码中,通过引用前面子表达式匹配的文本,以实现成组匹配字符串。
var s ="<h1>title<h1><p>text<p>"; var r = /(<\/?\w+>).*\1/g; var a = s.match(r); //返回数组["<h1>title<h1>" , "<p>text<p>"]
【提示】
由于子表达式可以相互嵌套,它们的顺序将根据左括号的顺序来确定。例如,下面示例定义匹配模式包含多个子表达式。
var s = "abc"; var r = /(a(b(c)))/; var a = s.match(r); //返回数组["abc", "abc" , "bc" , "c"]
在这个模式中,共产生了3个反向引用,第一个是“(a(b(c)))”,第二个是“(b(c))”,第三个是“(c)”。它们引用的匹配文本分别是字符串"abc"、"bc"和"c"。
【注意】
对子表达式的引用,是指引用前面子表达式所匹配的文本,而不是子表达式的匹配模式。如果要引用前面子表达式的匹配模式,则必须使用下面方式,只有这样才能够达到匹配目的。
var s ="<h1>title</h1><p>text</p>"; var r = /((<\/?\w+>).*(<\/?\w+>))/g; var a = s.match(r); //返回数组["<h1>title</h1>","<p>text</p>"]
反向引用在开发中主要有以下几种常规用法。
【示例2】在正则表达式对象的test()方法,以及字符串对象的match()和search()等方法中使用。在这些方法中,反向引用的值可以从RegExp()构造函数中获得。
var s = "abcdefghijklmn"; var r = /(\w)(\w)(\w)/; r.test(s); console.log(RegExp.$1); //返回第1个子表达式匹配的字符a console.log(RegExp.$2); //返回第2个子表达式匹配的字符b console.log(RegExp.$3); //返回第3个子表达式匹配的字符c
通过上面示例可以看到,正则表达式执行匹配测试后,所有子表达式匹配的文本都被分组存储在RegExp()构造函数的属性内,通过前缀符号$与正则表达式中子表达式的编号来引用这些临时属性。其中属性$1标识符指向第一个值引用,属性$2标识符指向第二个值引用,依此类推。
【示例3】可以直接在定义的字符模式中包含反向引用。这可以通过使用特殊转义序列(如\l、\2等)来实现(详细内容可以参阅上一节内容)。
var s = "abcbcacba"; var r = /(\w)(\w)(\w)\2\3\1\3\2\1/; var b = r.test(s); //验证正则表达式是否匹配该字符串 console.log(b); //返回true
在上面示例的正则表达式中,“\1”表示对第一个反向引用(\w)所匹配的字符a引用,“\2”表示对第二个反向引用(\w)所匹配的字符b引用,“\3”表示对第二个反向引用(\w)所匹配的字符c引用。
【示例4】可以在字符串对象的replace()方法中使用。通过使用特殊字符序列$1、$2、$3等来实现。例如,在下面的示例中将颠倒相邻字母和数字的位置:
var s = "aa11bb22c3d4e5f6"; var r = /(\w+?)(\d+)/g; var b = s.replace(r,"$2$1"); console.log(b); //返回字符串"11aa22bb3c 4d5e6f"
在上面例子中,正则表达式包括两个分组,第一个分组匹配任意连续的字母,第二个分组匹配任意连续的数字。在replace()方法的第二个参数中,$1表示对正则表达式中第一个子表达式匹配文本的引用,而$2表示对正则表达式中第二个子表达式匹配文本的引用,通过颠倒$1和$2标识符的位置,即可实现字符串的颠倒替换原字符串。