JavaScript高級程序設計第五章引用類型——RegExp類型

ECMAScript通過RegExp類型來支持正則表達式。

var expression = / pattern / flags ;//pattern模式 flags 標志

其中的模式(pattern)部分可以是任何簡單或復雜的正則表達式,可以包含字符串,限定符,分組,向前查找以及反向引用。每個正則表達式都可帶有一個或多個標志(flags),用以標明正則表達式的行為。

正則表達式的匹配模式支持下列3個標志:

g:表示全局(global)模式,即模式將被應用於所有字符串,而不是在發現第一個匹配時立即停止;

i:表示不區分大小寫(case-insensitive)模式,即在確定匹配項時忽略模式與字符串大小寫;

m:表示多行(multiline)模式,即在到達一行文本末尾時還會繼續查找下一行中是否存在與模式匹配的項。

因此,一個正則表達式就是一個模式與上述3個標志的組合體。

//匹配字符串中所有"at"的實例
var pattern1 = /at/g;
//匹配第一個"bat"或"cat",不區分大小寫
var pattern2 = /[bc]at/i;
//匹配所有以"at"結尾的3個字符的組合,不區分大小寫
var pattern3 = /.at/gi;

與其他語言中的正則表達式類似,模式中使用的所有元字符都必須轉義。正則表達式中的元字符包括:

( [ { \ ^ $ | ) ? * + . ] }

這些元字符在正則表達式中都有一或多種特殊用途,因此如果想要匹配字符串中包含的這些字符,就必須對他們進行轉義,下面幾個例子:

//匹配第一個"bat"或"cat",不區分大小寫
var pattern1 = /[bc]at/i;
//匹配第一個"[bc]at",不區分大小寫
var pattern2 = /\[bc\]at/i;  //對其中的兩個方括號進行轉義
//匹配所有以"at"結尾的3個字符的組合,不區分大小寫
var pattern3 = /.at/gi;  //句點表示位於"at"之前的任意一個可以構成匹配項的字符
//匹配所有".at",不區分大小寫
var pattern4 = /\.at/gi;  //必須對句點本身進行轉義

前面舉的這些例子都是以字面量形式來定義的正則表達式。另一種創建正則表達式的方式是使用RegExp構造函數,它接收兩個參數:一個是要匹配的字符串模板,另一個是可選的標志字符串。可以使用字面量定義的任何表達式,都可以使用構造函數來定義,如下面例子:

//匹配第一個"bat"或"cat",不區分大小寫
var pattern1 = /[bc]at/i;
//與pattern1相同,隻不過是使用構造函數創建的
var pattern2 = new RegExp("[bc]at","i");

在此,pattern1和pattern2是兩個完全等價的正則表達式。要註意的是,傳遞給RegExp構造函數的兩個參數都是字符串。所以在某些情況下要對字符進行雙重轉義。所有元字符都必須雙重轉義,那些已經轉義過的字符也是如此,例如\n(字符\在字符串中通常被轉義為\\,而在正則表達式字符串中就會變成\\\\),下面給出一些模式:

字面量模式????????????????????? ? 等價的字符串(RegExp構造函數)

/ \[bc\]at /????????????????????? ? " \\[bc\\]at "

/ \.at /????????????????????????????? ? " \\.at "

/ name\ /age /????????????????? ? " name \\ /age "

/ \d. \d{1,2} /????????????????????? ? " \\d. \\d{1,2} "

/ \w\\hello\\123/????????????????? ? " \\w\\\\hello\\\\123 "

使用正則表達式字面量和使用RegExp構造函數創建的正則表達式不一樣。在ECMAScript3中,正則表達式字面量始終會共享同一個RegExp實例,在使用構造函數創建的每一個新RegExp實例都是一個新實例,看下面例子:

var re = null,
    i;

for( i = 0; i < 10; i++){
     re = /cat/g;
     re.test("catastrophe");
}

for(i = 0; i < 10; i++){
    re = new RegExp("cat","g");
    re.test("catastrophe");
}

在第一個循環中,即使是循環體中指定的,但實際上隻為/cat/創建瞭一個RegExp實例。由於實例屬性不會重置,所以在循環中再次調用test()方法會失敗。這是因為第一次調用test()找到瞭"cat",但第二次調用是從索引為3的字符(上一次匹配的末尾)開始的,所以就找不到"cat"瞭,由於會測試到字符串末尾,所以下一次再調用test()就又從頭開始瞭。

第二個循環使用RegExp構造函數在每次循環中創建正則表達式。因為每次迭代都會創建一個新的RegExp實例,所以每次調用test()都會返回true。

ECMAScript5明確規定,使用正則表達式字面量必須像直接調用RegExp構造函數一樣,每次都創建新的RegExp實例。

5.4.1RegExp實例屬性

RegExp的每個實例都具有下列屬性,通過這些屬性可以取得有關模式的各種信息。

1.global:佈爾值,表示是否設置瞭g標志。

2.ignoreCase:佈爾值,表示是否設置瞭i標志。

3.lastIndex:整數,表示開始搜索下一個匹配項的字符位置,從0算起。

4.multiline:佈爾值,表示是否設置瞭m標志。

5.source:正則表達式的字符串表示,按照字面量形式而非傳入構造函數中的字符串模式返回。

通過這些屬性可以獲知一個正則表達式的各方面信息,但卻沒有多大用處,因為這些信息全部包含在模式聲明中。例如:

var pattern1 = /\[bc\]at/i;

alert(pattern1.global);//false
alert(pattern1.ignoreCase);//true
alert(pattern1.lastIndex);//0
alert(pattern1.multiline);//false
alert(pattern1.source);//"\[bc\]at"
var pattern2 = new RegExp("\\[bc\\]at","i");

alert(pattern2.global);//false
alert(pattern2.ignoreCase);//true
alert(pattern2.lastIndex);//0
alert(pattern2.multiline);//false
alert(pattern2.source);//"\[bc\]at"

我們註意到,盡管第一個模式使用的是字面量,第二個模式使用瞭RegExp構造函數,但他們的source屬性是相同的,可見,source屬性保存的是規范形式的字符串,即字面量形式所用的字符串。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。