正則表示式--RegExp物件
正則表示式是通過RegExp物件來表示的。除了RegExp()建構函式之外,RegExp物件還支援三個方法和一些屬性。接下來會對RegExp模式匹配方法和屬性展開講述。
RegExp()建構函式帶有兩個字串引數,其中第二個引數是可選的,RegExp()用以建立新的RegExp物件。第一個引數包含正則表示式的主體部分,也就是正則表示式直接量中兩條斜線之間的文字。需要注意的是,不論是字串直接量還是正則表示式,都使用“\”字元作為轉義字元的字首,因此當給RegExp()傳入一個字串表述的正則表示式時,必須將“\”替換成“\\”。RegExp()的第二個引數是可選的,如果提供第二個引數,它就指定正則表示式的修飾符。不過只能傳入修飾符g、i、m或者它們的組合。比如:
//全域性匹配字串中的5個數字,注意這裡使用了"\\",而不是"\"
var zipcode=new RegExp("\\d{5}","g");
RegExp()建構函式非常有用,特別是在需要動態建立正則表示式的時候,這種情況往往沒辦法通過寫死在程式碼中的正則表示式直接量來實現。例如,如果待檢索的字串是由使用者輸入的,就必須使用RegExp()建構函式,在程式執行時建立正則表示式。
-
RegExp的屬性
每個RegExp物件都包含5個屬性。屬性source是一個只讀的字串,包含正則表示式的文字。屬性global是一個只讀的布林值,用以說明這個正則表示式是否帶有修飾符g。屬性ignoreCase也是一個只讀的布林值,用以說明正則表示式是否帶有修飾符i。屬性multiline是一個只讀的布林值,用以說明正則表示式是否帶有修飾符m。最後一個屬性lastIndex,它是一個可讀/寫的整數。如果匹配模式帶有g修飾符,這個屬性儲存在整個字串中下一次檢索的開始位置,這個屬性會被exec()和test()方法用到,下面會講到。
-
RegExp的方法
RegExp物件定義了兩個用於執行模式匹配操作的方法。它們的行為和上文介紹過的String方法很類似。RegExp最主要的執行模式匹配的方法是exec(),它與10.2節介紹過的String方法match()相似,只是RegExp方法的引數是一個字串,而String方法的引數是一個RegExp物件。exec()方法對一個指定的字串執行一個正則表示式,簡言之,就是在一個字串中執行匹配檢索。如果它沒有找到任何匹配,它就返回null,但如果它找到了一個匹配,它將返回一個數組,就像match()方法為非全域性檢索返回的陣列一樣。這個陣列的第一個元素包含的是與正則表示式相匹配的字串,餘下的元素是與圓括號內的子表示式相匹配的子串。屬性index包含了發生匹配的字元位置,屬性input引用的是正在檢索的字串。
和match()方法不同,不管正則表示式是否具有全域性修飾符g,exec()都會返回一樣的陣列。回憶一下,當match()的引數是一個全域性正則表示式時,它返回由匹配結果組成的陣列。相比之下,exec()總是返回一個匹配結果,並提供關於本次匹配的完整資訊。當呼叫exec()的正則表示式物件具有修飾符g時,它將把當前正則表示式物件的lastIndex屬性設定為緊挨著匹配子串的字元位置。當同一個正則表示式第二次呼叫exe c()時,它將從lastIndex屬性所指示的字元處開始檢索。如果exec()沒有發現任何匹配結果,它會將lastIndex重置為0(在任何時候都可以將lastIndex屬性設定為0,每當在字串中找最後一個匹配項後,在使用這個RegExp物件開始新的字串查詢之前,都應當將lastIndex設定為0)。這種特殊的行為使我們可以在用正則表示式匹配字串的過程中反覆呼叫exec(),比如:
var pattern=/Java/g;
var text="JavaScript is more fun than Java!";
var result;
while((result=pattern.exec(text))!=null){
alert("Matched'"+result[0]+"'"+
"at position"+result.index+
";next search begins at"+pattern.lastIndex);
}
另外一個RegExp方法是test(),它比exec()更簡單一些。它的引數是一個字串,用test()對某個字串進行檢測,如果包含正則表示式的一個匹配結果,則返回true:
var pattern=/java/i;
pattern.test("JavaScript");//返回true
呼叫test()和呼叫exec()等價,當exec()的返回結果不是null時,test()返回true。由於這種等價性,當一個全域性正則表示式呼叫方法test()時,它的行為和exec()相同,因為它從lastIndex指定的位置處開始檢索某個字串,如果它找到了一個匹配結果,那麼它就立即設定lastIndex為當前匹配子串的結束位置。這樣一來,就可以使用test()來遍歷字串,就像用exec()方法一樣。
與exec()和test()不同,String方法search()、replace()和match()並不會用到lastIndex屬性。實際上,String方法只是簡單地將lastIndex屬性值重置為0。如果讓一個帶有修飾符g的正則表示式對多個字串執行exec()或test(),要麼在每個字串中找出所有的匹配以便將lastIndex自動重置為零,要麼顯式將lastIndex手動設定為0(當最後一次檢索失敗時需要手動設定lastIndex)。如果忘了手動設定lastIndex的值,那麼下一次對新字串進行檢索時,執行檢索的起始位置可能就不是字串的開始位置,而可能是任意位置[7]。當然,如果RegExp不帶有修飾符g,則不必擔心會發生這種情況。同樣要記住,在ECMAScript 5中,正則表示式直接量的每次計算都會建立一個新的RegExp物件,每個新RegExp物件具有各自的lastIndex屬性,這勢必會大大減少“殘留”lastIndex對程式造成的意外影響。