正則的解釋
正則表達(dá)式的創(chuàng)建
// 兩個正斜杠定義正則字面量的邊界
var reg = /test/;
// 構(gòu)造RegExp實(shí)例
var reg = new RegExp("test");
3個匹配標(biāo)志的使用方法
// i 表示不區(qū)分大小寫
// g 表示全局匹配,而不是只匹配第一次出現(xiàn)的結(jié)果
// m 表示允許多行匹配
var reg = /test/igm;
var reg = new RegExp("test","igm");
正則的術(shù)語與操作符
匹配一個有限字符集中的某一個字符
// 表示匹配a,b,c中的任意一個字符
var reg = /[abc]/;
在中括號第一個括號后面加入^,表示匹配該組有限字符集以外的字符
// 表示匹配除了a,b,c以外的任意字符
var reg = /[^abc]/;
在字符集之間加入-,表示制定一個范圍
// 表示匹配a到m之間的任意字符,包括a和m
var reg = /[a-m]/;
轉(zhuǎn)義,在正則表達(dá)式中,字母和數(shù)字都能代表自己本身,但類似$-.[]等特殊字符都有其他含義,要匹配這些字符,需要用\對其進(jìn)行轉(zhuǎn)義
// 表示匹配$字符
var reg = /\$/;
匹配的開始與結(jié)束
當(dāng)^作為正則表達(dá)式的第一個字符時,表示必須從字符串的開頭進(jìn)行匹配。
// 表示匹配以abc開頭的字符串
var reg = /^abc/;
當(dāng)$作為正則表達(dá)式的最后一個字符時,表示該模式必須出現(xiàn)在字符串的結(jié)尾。
// 表示匹配以abc結(jié)尾的字符串
var reg = /abc$/;
同時使用^和$時,表示匹配模式必須包含整個字符串,即匹配模式就是字符串本身,沒有任何其他字符。
// 表示匹配"abc"這個字符串,"abcabc"之類的不會匹配
var reg = /^abc$/;
重復(fù)出現(xiàn)
在一個字符后面加一個?,表示該字符是可選的,也就是可以出現(xiàn)一次或不出現(xiàn)
// 表示匹配abc或者bc,
var reg = /a?bc/;
在一個字符后面加一個+,表示該字符可以出現(xiàn)一次或多次
// 表示匹配abc或者aaabc,
var reg = /a+bc/;
在一個字符后面加一個*,表示該字符可以出現(xiàn)零次或多次,即任意次數(shù)
// 表示匹配abc或者aaabc或者bc,
var reg = /a*bc/;
在字符后跟花括號,在起重指定一個數(shù)字,表示該字符出現(xiàn)的次數(shù)
// 表示匹配aaaa,
var reg = /a{4}/;
在字符后跟花括號,在起重指定一個區(qū)間,表示該字符出現(xiàn)的次數(shù)區(qū)間
// 表示匹配a出現(xiàn)次數(shù)在4到10之間任意次數(shù)的字符串,包括4次和10次
var reg = /a{4,10}/;
次數(shù)區(qū)間第二個數(shù)值是可選的,當(dāng)沒有第二個數(shù)字是,表示匹配一個開區(qū)間
// 表示匹配a出現(xiàn)次數(shù)至少4次
var reg = /a{4,}/;
以上重復(fù)操作符可以是貪婪的或者非貪婪的,默認(rèn)情況下是貪婪的,表示盡可能多的匹配,例如,匹配"aaa"字符串時,/a+/模式將匹配所有3個a。在操作符后面加上?,表示非貪婪模式,將進(jìn)行最小限度的匹配,匹配"aaa"字符串時,/a+?/模式只會匹配一個a字符。因?yàn)橐粋€a字符就滿足+表示的一次或多次的情況。
預(yù)定義字符類
\t 水平制表符
\b 空格
\n 換行符
. 匹配除換行以外的任意字符
\d 匹配任意數(shù)字,等價于[0-9]
\D 匹配任意非數(shù)字,等價于[^0-9]
\w 匹配包括下劃線的任意單詞字符,等價于[A-Za-z0-9_]
\W 匹配任何非單詞字符,等價于[^A-Za-z0-9_]
\s 匹配任何空白符,包括空格,制表符,換頁符等
\S 匹配任何非空白字符
\b 匹配單詞邊界
\B 匹配非單詞邊界
分組
在為匹配模式加上小括號,可以讓其成為一個分組,后續(xù)添加的操作符可以影響整個分組。
// 表示匹配出現(xiàn)一次或連續(xù)多次的ab字符串,例如"xxxabxxx","xxxabababxxx"
var reg = /(ab)+/;
或操作符
豎線|表示或操作符
// 表示匹配a或b
var reg = /a|b/;
// 表示匹配出現(xiàn)一次或多次的"ab"或"ba"
var reg = /(ab)+|(ba)+/;
反向引用
反斜杠后面加一個數(shù)字表示要引用之前已經(jīng)匹配到的分組
// \1表示再匹配一次第一個分組([ab])匹配到的內(nèi)容,\2表示再匹配一次第二個分組(a)匹配到的內(nèi)容。
// 并且不是再次對分組中的模式進(jìn)行匹配,而是對已經(jīng)匹配到的一模一樣的內(nèi)容進(jìn)行精確匹配。
// 例如第一個分組([ab])匹配到了字符b,\1匹配的就也必須是字符b
var reg = /([ab])(a)\1\2/;
反向引用常用來匹配元素的標(biāo)簽
// \1表示對第一個分組(\w+)匹配到的內(nèi)容再次匹配,內(nèi)容必須完全相同。因?yàn)闃?biāo)簽的開始和關(guān)閉是相同的。
var reg =/<(\w+)>.*<\/\1>/;
var a = "<strong>some thing</strong>";
console.log(reg.test(a)); // true
正則表達(dá)式的編譯
正則表達(dá)式的編譯發(fā)生在第一次被創(chuàng)建的時候,而執(zhí)行則是發(fā)生在我們使用編譯過的正則表達(dá)式進(jìn)行字符串匹配的時候。所以正則表達(dá)式只應(yīng)該編譯一次,并將其保存在一個變量中以供后續(xù)使用,這是一個重要的優(yōu)化過程。每次創(chuàng)建的正則表達(dá)式都是一個新的對象,其結(jié)果都是獨(dú)一無二的。
使用構(gòu)造器(new RegExp())可以通過動態(tài)的字符串創(chuàng)建正則表達(dá)式。
捕獲匹配的片段
匹配到的內(nèi)容中,每一個括號分組都是一個片段,使用字符串的match()方法可以捕獲匹配的片段。
在非全局匹配時。其返回結(jié)果是一個數(shù)組,第一個索引的值是該匹配的完整結(jié)果,之后的參數(shù)是每一個捕獲的片段。
在全局匹配時。其返回結(jié)果也是一個數(shù)組,但數(shù)組的值是所有的匹配結(jié)果,每一個匹配結(jié)果的捕獲片段是不會返回的。
// 非全局匹配
var reg =/<(\w+)([^>]*)>/;
var a = '<div class="abc">hello</div>';
var b = a.match(reg);
console.log(b); // ["<div class="abc">", "div", " class="abc""]
// 全局匹配
var reg =/(\w+)([^>]*)>/g;
var a = '<div class="abc">hello</div>';
var b = a.match(reg);
console.log(b); // ["div class="abc">", "hello</div>"]
正則表達(dá)式的exec()方法,可以對同一個字符串進(jìn)行多次匹配,每一次匹配都會返回下一個匹配的結(jié)果
var reg =/<(\w+)([^>]*)>/g;
var a = '<div class="abc"><p>hello <span>world</span></p></div>';
var b = reg.exec(a);
var c = reg.exec(a);
var d = reg.exec(a);
console.log(b); // ["<div class="abc">"]
console.log(c); // ["<p>"]
console.log(d); // ["<span>"]
捕獲的引用
在replace()方法中,可以使用$1,$2,$3這樣的語法來引用之前捕獲到的分組。
// 正則中的$1表示第一個捕獲到的分組中的內(nèi)容,即[A-Z]匹配到的內(nèi)容。
var a = 'borderColor';
var b = a.replace(/([A-Z])/g,"-$1").toLowerCase();
console.log(b); // border-color
沒有捕獲的分組
在分組的左括號后加一個?:標(biāo)記,表示這個分組不需要被捕獲。
var reg = /(?:-[A-Z])/;
var a = 'border-Color';
var b = a.match(reg);
// 只返回了匹配的內(nèi)容,沒有返回分組中的內(nèi)容
console.log(b[1]); // undefined
在不需要捕獲的時候,盡量可能的使用非捕獲分組,減少引擎的工作量。
利用函數(shù)進(jìn)行替換
replece()方法的第二個參數(shù)可以傳入一個函數(shù),全局模式下每個匹配都會調(diào)用這個函數(shù),該函數(shù)有一個參數(shù)列表,分別為:
- 匹配的完整文本
- 匹配的捕獲,一個捕獲對應(yīng)一個參數(shù)
- 匹配字符在元字符串中的索引
- 源字符串
function up(all,str) {
return "-"+str.toLowerCase();
}
var a = 'borderBottomColor';
var b = a.replace(/([A-Z])/g,up);
console.log(b); // border-bottom-color
利用這一特性可以修改一些數(shù)據(jù)的格式,例如將"a=1&a=2&a=3&b=4&b=5"修改為"a=1,2,3&b=4,5"。
function up(str) {
var keys = {}; // 保存數(shù)據(jù)
str.replace(/([^=&]+)=([^&]+)/g,function (all, key, value) {
keys[key]=keys[key]?keys[key]+","+value:value;
});
var result = [];
for (var key in keys){
result.push(key+"="+keys[key]);
}
return result.join("&");
}
var a = 'a=1&a=2&a=3&b=4&b=5';
console.log(up(a)); // a=1,2,3&b=4,5
常見問題
// 刪除前后空格,低端瀏覽器不支持trim()方法
var a = ' abc abc ';
console.log(a.replace(/^\s+|\s+$/g,"")); // abc abc
// 匹配換行符,/[\S\s]*/ 表示匹配所有字符
var a = 'abc\nabc';
console.log(/[\S\s]*/.exec(a)[0]);
// 匹配Unicode
var a = '\u5FCD\u8005\u30D1\u30EF\u30FC';
console.log(a.match(/[\w\u0080-\uFFFF_-]+/)[0]); // 忍者パワー