建立正規表達式
1.使用RegExp()構造函數來建立
RegExp()構造函數非常有用,特别是在需要動态建立正規表達式的時候,這種情況往往沒辦法通過寫死在代碼中的正規表達式直接量來實作。
例如,如果待檢索的字元串是由使用者輸入的,就必須使用RegExp()構造函數,在程式運作時建立正規表達式
var pattern = new RegExp("s$");
2.使用直接量文法來建立
var pattern = /s$/;
RegExp對象的屬性
每個RegExp對象(即正規表達式對象)都有5個屬性。
屬性 | 屬性描述 |
---|---|
source | 隻讀的字元串,包含正規表達式的文本 |
global | 隻讀的布爾值,用以說明這個正規表達式是否帶有修飾符g |
ignoreCase | 隻讀的布爾值,用以說明正規表達式是否帶有修飾符i |
multiline | 隻讀的布爾值,用以說明正規表達式是否帶有修飾符m |
lastIndex | 可讀/寫的整數,如果比對模式帶有g修飾符,這個屬性存儲在整個字元串中下一次檢索的開始位置,這個屬性會被exec()和test()方法用到,下面會講到 |
直接量字元
字元 | 比對 |
---|---|
a-zA-Z0-9 | 比對自身 |
\o | NUL字元(\u0000) |
\t | 制表符(\u0009) |
\n | 換行符(\u000A) |
\v | 垂直制表符(\u000B) |
\f | 換頁符(\u000C) |
\r | 回車符(\u000D) |
\xnn | 由十六進制數nn制定的拉丁字元,例如,\x0A等價于\n |
\uxxxx | 由十六進制數xxxx制定的Unicode字元,例如\u0009等價于\t |
\cX | 控制字元^X,例如,\cJ等價于換行符\n |
字元類
将直接量字元單獨放進方括号内就組成了字元類。一個字元類可以比對它所包含的任意字元
[...] | 方括号内的任意字元 |
[^...] | 不在方括号内的任意字元 |
. | 除換行符和其他Unicode行終止符之外的任意字元 |
\w | 任何ASCII字元組成的單詞,等價于[a-zA-Z0-9] |
\W | 任何不是ASCII字元組成的單詞,等價于[^a-zA-Z0-9] |
\s | 任何Unicode空白符 |
\S | 任何不是Unicode空白符的字元,注意\S和\w不同 |
\d | 任何ASCII數字,等價于[0-9] |
\D | 除了ASCII數字之外的任何字元,等價于[^0-9] |
[\b] | 倒退直接量(特例) |
重複
含義 | |
---|---|
{n,m} | 比對前一項至少n次,但不能超過m次 |
{n,} | 比對前一項n次或更多次 |
{n} | 比對前一項n次 |
? | 比對前一項0次或者1次,也就是說前一項是可選的。等價于{0,1} |
+ | 比對前一項一次貨多次,等價于{1,} |
* | 比對前一項0次或多次,等價于{0,} |
非貪婪重複
- 上表中列出的比對重複字元是盡可能多地比對,而且允許後續的正規表達式繼續比對。是以,我們稱之為“貪婪的”比對。
- 我們同樣可以使用正規表達式進行非貪婪比對。隻須在待比對的字元後跟随一個問号即可:"??"、"+?"、"*?"或"{1,5}?"。
- 比如,正規表達式 /a+/ 可以比對一個或多個連續的字母a。當使用 "aaa" 作為比對字元串時,正規表達式會比對它的三個字元。但是 /a+?/ 也可以比對一個或多個連續字母a,但它是盡可能少地比對。我們同樣将 "aaa" 作為比對字元串,但後一個模式隻能比對第一個a。
- 使用非貪婪的比對模式所得到的結果可能和期望并不一緻。考慮以下正規表達式 /a+b/ ,它可以比對一個或多個a,以及一個b。當使用 "aaab" 作為比對字元串時,它會比對整個字元串。現在再試一下非貪婪比對的版本 /a+?b/ ,它比對盡可能少的a和一個b。當用它來比對 "aaab" 時,你期望它能比對一個a和最後一個b。但實際上,這個模式卻比對了整個字元串,和該模式的貪婪比對一模一樣。
- 這是因為正規表達式的模式比對總是會尋找字元串中第一個可能比對的位置。由于該比對是從字元串的第一個字元開始的,是以在這裡不考慮它的子串中更短的比對。
指定比對位置
使用正規表達式的錨字元可以指定比對的位置,可以指定正規表達式的比對位置實在字元串的開頭、結尾還是單詞的邊界處等。
^ | 比對正規表達式的開頭,在多行檢索中,比對一行的開頭 |
$ | 比對正規表達式的結尾,在多行檢索中,比對一行的結尾 |
\b | 比對一個單詞的邊界,簡言之,就是位于字元\w和\W之間的位置,或位于字元\w和字元串的開頭或者結尾的位置(但是需要注意,[\b]比對的是倒退符) |
\B | 比對非單詞邊界的位置 |
(?=p) | 零寬正向先行斷言,要求接下來的字元都與p比對,但不能包含比對p的那些字元 |
(?!p) | 零寬負向先行斷言,要求接下來的字元都不與p比對 |
修飾符
正規表達式的修飾符,用以說明進階比對模式的規則。修飾符的位置是放在“/”符号之外的,也就是第二條斜線之後;或者是正規表達式的構造函數的第二個參數位置,
// 正規表達式構造函數的第二個參數,用來指定修飾符
var pattern = new RegExp("s$","igm");
// 直接量文法中,第二條斜線之後,指定修飾符
var pattern = /s$/igm;
i | 執行不區分大小寫的比對 |
g | 執行一個全局比對,簡言之,及找到所有的比對,而不是找到第一個比對之後即停止 |
m | 多行比對模式,^比對每一行的開頭和字元串的開頭,$比對每一行的結束和字元串的結束 |
選擇
使用選擇符,可以指定比對的是該符号左邊的子表達式還是右邊的子表達式。例如:
|
可以比對字元串"ab",也可以比對字元串"cd",還可以比對字元串"ef"
/ab|cd|ef/
| | 比對的是該符号左邊的子表達式還是右邊的子表達式 |
分組
分組是把單獨的項組合成子表達式,以便可以像處理一個獨立的單元那樣用、
|
*
或者
+
?
等來對單元内的項進行處理。
不僅如此,分組後的子表達式還可以用于後期的引用,能夠更大限度滿足我們的需求。
(...) | 組合,将幾個項組合為一個單元,這個單元可以通過 ** 或者 等符号加以修飾,而且可以記住群組合相比對的字元串以供此後的引用使用 |
(?:) | 隻組合,把項組合到一個單元,但是不記憶和改組相比對的字元 |
引用
對正規表達式中前一個子表達式的引用,并不是指對子表達式模式的引用,而指的是與那個模式相比對的文本的引用。
正規表達式中有多個帶圓括号的子表達式,可以使用
\n
的形式進行引用。
例如:
引用的是第一個帶圓括号的子表達式,
\1
\3
引用的是第三個帶
圓括号的子表達式。注意,因為子表達式可以嵌套另一個子表達式,是以它的位置是參與計數的左括号的位置。
和第n個分組第一次比對的字元相比對,組是圓括号中的子表達式(也有可能是嵌套的),組索引是從左到右的左括号書。但是注意:"(?:)"形式的分組不編碼,即不能引用 |
用于模式比對的String方法
1.String.search(n)
- 參數:正規表達式
- 傳回值:傳回第一個與之比對的子串的起始位置,如果找不到比對的子串,它将傳回-1。
- 示例代碼:
"JavaScript".search(/script/i); // 傳回值為4
- 備注:如果search()的參數不是正規表達式,則首先會通過RegExp構造函數将它轉換成正規表達式。search()方法不支援全局檢索,因為它忽略正規表達式參數中的修飾符g。
2.String.replace(n1,n2)
- 參數:第一個參數是一個正規表達式,第二個參數是要進行替換的字元串
- 作用:
- 這個方法會對調用它的字元串進行檢索,使用指定的模式來比對。
- 如果正規表達式中設定了修飾符g,那麼源字元串中所有與模式比對的子串都将替換成第二個參數指定的字元串。
- 如果不帶修飾符g,則隻替換所比對的第一個子串。
var text="Hello javascript ! javascript is very good !";
// 将所有不區分大小寫的javascript都替換成大小寫正确的JavaScript
var text2=text.replace(/javascript/gi,"JavaScript");
// 最終的text2是 "Hello JavaScript ! JavaScript is very good !"
console.log(text2);
- 備注:。如果replace()的第一個參數是字元串而不是正規表達式,則replace()将直接搜尋這個字元串,而不是像search()一樣首先通過RegExp()将它轉換為正規表達式。
3.String.match(n)
- 傳回值:
- 傳回的是一個由比對結果組成的數組。如果該正規表達式設定了修飾符g,則該方法傳回的數組包含字元串中的所有比對結果。
- 如果這個正規表達式沒有設定修飾符g,match()就不會進行全局檢索,它隻檢索第一個比對。但即使match()執行的不是全局檢索,它也傳回一個數組。在這種情況下,數組的第一個元素就是比對的字元串,餘下的元素則是正規表達式中用圓括号括起來的子表達式。
- 是以,如果match()傳回一個數組a,那麼a[0]存放的是完整的比對,a[1]存放的則是與第一個用圓括号括起來的表達式相比對的子串,以此類推。
var url=/(\w+):\/\/([\w.]+)\/(\S*)/;
var text="Visit my blog at http://www.example.com/~david";
var result=text.match(url);
if(result!=null){
var fullurl=result[0]; //包含"http://www.example.com/~david"
var protocol=result[1]; //包含"http"
var host=result[2]; //包含"www.example.com"
var path=result[3]; //包含"~david"
}
4.String.split(n)
- 作用:将傳入的參數作為邊界條件,将調用它的字元串拆分為一個子串組成的數組
- 傳回值:傳回拆分後的字元串組成的數組
"123,456,789".split(",");//傳回["123","456","789"]
"1,2,3,4,5".split(/\s*,\s*/);//傳回["1","2","3","4","5"]
用于模式比對的RegExp方法
1.RegExp.exec(n)
- 參數:字元串
- 作用:exec()方法對一個指定的字元串執行一個正規表達式,簡言之,就是在一個字元串中執行比對檢索。
-
- 如果它沒有找到任何比對,它就傳回null;
- 如果它找到了一個比對,它将傳回一個數組,就像match()方法為非全局檢索傳回的數組一樣。
- 這個數組的第一個元素包含的是與正規表達式相比對的字元串,餘下的元素是與圓括号内的子表達式相比對的子串。
- 和match()方法不同,不管正規表達式是否具有全局修飾符g,exec()都會傳回一樣的數組。
- 回憶一下,當match()的參數是一個全局正規表達式時,它傳回由比對結果組成的數組。相比之下,exec()總是傳回 目前比對的一個比對結果 ,并提供關于本次比對的完整資訊。
- 當調用exec()的正規表達式對象具有修飾符g時,它将把目前正規表達式對象的lastIndex屬性設定為緊挨着比對子串的字元位置。
- 當同一個正規表達式第二次調用exec()時,它将從lastIndex屬性所訓示的字元處開始檢索。如果exec()沒有發現任何比對結果,它會将lastIndex重置為0(在任何時候都可以将lastIndex屬性設定為0,每當在字元串中找最後一個比對項後,在使用這個RegExp對象開始新的字元串查找之前,都應當将lastIndex設定為0)。
- 這種特殊的行為使我們可以在用正規表達式比對字元串的過程中反複調用exec(),
var pattern=/java/img;
var text="I love JAVA and JavaScript. I think javascript is more interesting";
// 第一次調用,傳回的資訊:["JAVA", index: 7, input: "text的文本内容", groups: undefined]
console.log(pattern.exec(text));
// 第二次調用,傳回的資訊:["Java", index: 16, input: "text的文本内容", groups: undefined]
console.log(pattern.exec(text));
// 第三次調用,傳回的資訊:["java", index: 36, input: "text的文本内容", groups: undefined]
console.log(pattern.exec(text));
- 備注:exec()方式是RegExp對象的主要方法,大家仔細閱讀上面的介紹,一定能明白這個方法。
2.RegExp.test(n)
- 傳回值:用test()對某個字元串進行檢測,如果包含正規表達式的一個比對結果,則傳回true,否則傳回false。
var pattern=/java/i;
pattern.test("JavaScript"); // 傳回true
pattern.test("feng"); // 傳回false