讀古今文學網 > 編寫高質量代碼:改善JavaScript程序的188個建議 > 建議41:正確使用正則表達式引用 >

建議41:正確使用正則表達式引用

正則表達式在執行匹配運算時會自動把每個分組(子表達式)匹配的文本都存儲在一個特殊的地方以備將來使用。這些存儲在分組中的特殊值被稱為反向引用。反向引用將遵循從左到右的順序,根據表達式中左括號字符的順序進行創建和編號。


var s="abcdefghijklmn";

var r=/(a(b(c)))/;

var a=s.match(r);//["abc","abc","bc","c"]


在這個分組匹配模式中,共產生了3個反向引用,第一個是「(a(b(c)))」,第二個是「(b(c))」,第三個是「(c)」。它們引用的匹配文本分別是字符串「abc」、「bc」和「c」。

反向引用在應用開發中主要有以下幾種常規用法。

1)在正則表達式對象的test方法,以及字符串對象的match和search等方法中使用。在這些方法中,反向引用的值可以從RegExp構造函數中獲得。例如:


var s="abcdefghijklmn";

var r=/(\w)(\w)(\w)/;

r.test(s);

alert(RegExp.$1);//第1個子表達式匹配的字符a

alert(RegExp.$2);//第2個子表達式匹配的字符b

alert(RegExp.$3);//第3個子表達式匹配的字符c


在正則表達式執行匹配測試後,所有子表達式匹配的文本都被分組存儲在RegExp構造函數的屬性內,通過前綴符號$與正則表達式中子表達式的編號來引用這些臨時屬性,其中屬性$1標識符指向第一個值引用,屬性$2標識符指向第二個值引用,依此類推。

2)可以直接在定義分組的表達式中包含反向引用。這可以通過使用特殊轉義序列(如\l、\2等)來實現。例如:


var s="abcbcacba";

var r=/(\w)(\w)(\w)\2\3\1\3\2\1/;

var b=r.test(s);//驗證正則表達式是否匹配該字符串

alert(b);//true


在上面的正則表達式中,「\1」表示對第一個反向引用(\w)所匹配的字符a的引用,「\2」表示對第二個反向引用(\w)所匹配的字符b的引用,「\3」表示對第二個反向引用(\w)所匹配的字符c的引用。

3)可以在字符串對象的replace方法中使用。通過使用特殊字符序列$1、$2、$3等來實現。例如,在下面的示例中將顛倒相鄰字母和數字的位置。


var s="aa11bb22c3d4e5f6";

var r=/(\w+?)(\d+)/g;

var b=s.replace(r,"$2$1");

alert(b);//"11aa22bb3c 4d5e6f"


在這個示例中,正則表達式包括兩個分組,第一個分組匹配任意連續的字母,第二個分組匹配任意連續的數字。在replace方法的第二個參數中,$1表示對正則表達式中第一個子表達式匹配文本的引用,而$2表示對正則表達式中第二個子表達式匹配文本的引用,通過顛倒$1和$2標識符的位置即可實現字符串的顛倒以替換原字符串。