RegExp的使用
- 基本文法
-
- 字面量建立
- RegExp構造函數
- RegExp執行個體屬性
- RegExp示例方法
-
- exec()
- test()
- toLocaleString()和toString()
- *RegExp構造函數的屬性
基本文法
ECMAScript通過RegExp類型支援正規表達式,正規表達式使用類似Perl的簡潔文法來建立。關于正規表達式的簡單介紹可以參考部落客的另一篇文章:正規表達式。
字面量建立
文法如下:
pattern代表模式,模式可以是任何簡單或複雜的正規表達式,包括字元類、限定符、分組、向前查找和反向作用。每個正規表達式可以帶零個或者多個的flags(标記),用于控制正規表達式的行為,常見的标記值有:
flags | 含義 |
---|---|
g | 全局模式,表示查找字元串的全部内容,而不是找到第一個比對的内容就結束 |
i | 不區分大小寫,表示在查找比對的時候忽略pattern和字元串的大小寫 |
m | 多行模式,表示查找到一行文本末尾時會繼續查找 |
y | 粘附模式,表示隻查找從lastInex開始及之後的字元串 |
u | Unicode模式,啟用Unicode比對 |
s | dotAll模式,表示元字元.比對任何字元,包括"\n"和"\r" |
使用不同模式和标記可以建立出不同的正規表達式,比如:
let pattern1 = /abc/g; //比對字元串中所有的abc
let pattern2 = /abc/i; //比對字元串中第一個出現的abc
let pattern3 = /abc/gi; //比對字元串中所有的abc,并且忽略大小寫
正規表達式中還會涉及到元字元的概念,元字元常見的有:{ 、} 、( 、) 、[ 、] 、\ 、^ 、$ 、| 、? 、* 、+ 、.(點)。元字元在正規表達式中都有着特殊的功能,要比對元字元本身的話,就需要用到轉義字元:“\”,例如:
let pattern1 = /[ab]d/g; //比對所有ad或bd
let pattern2 = /\[ab\]d/g; //比對所有的[ab]d
RegExp構造函數
除了上文的字面量建立正規表達式,RegExp構造函數也可以用于建立正規表達式,它的一般形式為:
let pattern1 = new RegExp("abc", "g");
//與let pattern1 = /abc/g;等價
這裡還需要注意的是,RegExp構造函數的兩個參數都是字元串,是以在某些情況下需要進行二次轉義,例如:
let pattern1 = /\[ab\]c/g;
let pattern2 = new RegExp("\\[ab\\]c","g");
這裡的pattern1和pattern2是等價的,其實也可以簡單地了解為如果想要用RegExp構造函數表示的話,轉義符号的數量是字面量的兩倍。
使用RegExp構造函數還可以基于原有的正規表達式,選擇性地修改它們的标記,例如:
let pattern1 = /abc/g;
console.log(pattern1); //輸出/abc/g
let pattern2 = new RegExp(pattern1);
console.log(pattern2); //輸出/abc/g
let pattern3 = new RegExp(pattern1, "i");
console.log(pattern3); //輸出/abc/i
RegExp執行個體屬性
RegExp執行個體常見的屬性有:
屬性 | 代表 |
---|---|
global | 布爾值,表示是否設定了g标記 |
ignoreCase | 布爾值,表示是否設定i标記 |
unicode | 布爾值,表示是否設定了u标記 |
sticky | 布爾值,表示是否設定了y标記 |
mutiline | 布爾值,表示是否設定了m标記 |
dotAll | 布爾值,表示是否設定了s标記 |
source | 正規表達式的字面量字元串(這裡與字面量的差別就是沒有開頭和結尾的斜杠) |
flags | 正規表達式的标記字元串 |
RegExp示例方法
exec()
RegExp示例的主要方法是exec(),主要用于配合捕獲組,(可以了解為一個括号就是一個捕獲組),exec方法隻接收一個參數,就是要應用模式的字元串,如果找到了比對項,就會傳回包含第一個比對資訊的數組;如果沒找到比對項,則傳回null。這裡要注意的是,傳回的數組雖然是Array的執行個體,但包含兩個額外的屬性:index和input,index是字元串中比對模式的起始位置,input是要查找的字元串。傳回數組的第一個元素是比對整個模式的字元串,其他元素是與表達式中的捕獲組比對的字元串。如果模式中沒有捕獲組,則數組隻有一個元素,具體例子如下:
let str = 'abcabce';
let pattern = /(.)b(.)/g;
let result = pattern.exec(str);
console.log(result);
console.log(result.input);
console.log(result.index);
console.log(result[0]);
console.log(result[1]);
console.log(result[2]);
結果如下:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0TPB1kenpmTycmeNBDOsJGcohVYsR2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLycDO4UTMwYTM0EDNwEjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
如果模式設定了全局模式,則每次調用exec()方法會傳回一個比對的資訊。如果沒有設定全局标記,則無論對同一個字元串調用多少次exec(),也隻會傳回第一個比對的資訊,如:
let str = 'cat, bat, sat, fat';
let pattern = /.at/;
let result = pattern.exec(str);
console.log(result.index); //0
console.log(result[0]); //cat
console.log(pattern.lastIndex); //0
result = pattern.exec(str);
console.log(result.index); //0
console.log(result[0]); //cat
console.log(pattern.lastIndex); //0
而如果當我們設定了全局标記:
let str = 'cat, bat, sat, fat';
let pattern = /.at/g;
let result = pattern.exec(str);
console.log(result.index); //0
console.log(result[0]); //cat
console.log(pattern.lastIndex); //3
result = pattern.exec(str);
console.log(result.index); //5
console.log(result[0]); //bat
console.log(pattern.lastIndex); //8
而當模式設定了粘附标記y,則每次調用exec()都隻會在lastIndex的位置上尋找比對項。粘附标記會覆寫全局标記。具體例子如下:
let str = 'cat, bat, sat, fat';
let pattern = /.at/y;
let result = pattern.exec(str);
console.log(result.index); //0
console.log(result[0]); //cat
console.log(pattern.lastIndex); //3
result = pattern.exec(str);
//以索引3對應的字元開頭找不到比對項,exec()傳回null
console.log(result); //null
//exec()沒有找到比對項,于是lastIndex設定為0
console.log(pattern.lastIndex); //0
//如果将lastIndex設定為5,讓exec()可以找到下一個比對項
pattern.lastIndex = 5;
result = pattern.exec(str);
console.log(result.index); //5
console.log(result[0]); //cat
console.log(pattern.lastIndex); //8
test()
test()用于測試特定的數值序列。如果輸入的文本與模式比對,則顯示比對成功的消息,一般用于驗證使用者的輸入:
let str = '123-123-12';
let pattern = /\d{3}-\d{3}-\d{2}/g;
let result = pattern.test(str);
if(result){
console.log('符合格式'); //輸出符合格式
}else{
console.log('不符合格式');
}
toLocaleString()和toString()
這兩個方法都是用于獲得正規表達式字面量的形式,無論正規表達式是字面量建立的還是RegExp構造函數建立的:
let pattern1 = new RegExp("abc", "g");
let pattern2 = /abc/g;
console.log(pattern1.toLocaleString()); //輸出/abc/g
console.log(pattern1.toString()); //輸出/abc/g
console.log(pattern2.toLocaleString()); //輸出/abc/g
console.log(pattern2.toString()); //輸出/abc/g
*RegExp構造函數的屬性
RegExp構造函數本身也有幾個屬性,這些屬性适用于作用域中的所有正規表達式,而且會根據最後執行的正規表達式操作而變化,這些屬性都有全名和簡寫,具體如下:
全名 | 簡寫 | 說明 |
---|---|---|
input | $_ | 最後搜尋的字元串 |
lastMatch | $& | 最後比對的文本 |
lastParen | $+ | 最後比對的捕獲組 |
leftContext | $` | input字元串中出現在lasMatch前的文本 |
rightContext | $’ | input字元串中出現在lasMatch後的文本 |
具體使用如下:
let text = "this is a sentence";
let pattern = new RegExp("(.)s","g");
if(pattern.test(text)){
console.log(RegExp.input);
console.log(RegExp.leftContext);
console.log(RegExp.rightContext);
console.log(RegExp.lastMatch);
console.log(RegExp.lastParen);
}
結果:
也可以使用簡寫:
let text = "this is a sentence";
let pattern = new RegExp("(.)s","g");
if(pattern.test(text)){
console.log(RegExp["$_"]);
console.log(RegExp["$`"]);
console.log(RegExp["$'"]);
console.log(RegExp["$&"]);
console.log(RegExp["$+"]);
}
RegExp構造函數還有幾個屬性,可以存儲最多9個捕獲組的比對項,通過RegExp.$1~RegExp.$9來通路。
RegExp構造函數的所有屬性都沒有任何Web标準出處,是以不要在生産環境中使用它們。