網(wǎng)上正則表達(dá)式的教程夠多了,但由于javascript的歷史比較悠久,也比較古老,因此有許多特性是不支持的。我們先從最簡單地說起,文章所演示的正則基本都是perl方式。
元字符
( [ { \ ^ $ | ) ? * + .
預(yù)定義的特殊字符
字符 | 正則 | 描述 |
\t | /\t/ | 制表符 |
\n | /\n/ | 制表符 |
\r | /\r/ | 回車符 |
\f | /\f/ | 換頁符 |
\a | /\a/ | alert字符 |
\e | /\e/ | escape字符 |
\cX | /\cX/ | 與X相對應(yīng)的控制字符 |
\b | /\b/ | 與回退字符 |
\v | /\v/ | 垂直制表符 |
\0 | /\0/ | 空字符 |
字符類
簡單類
原則上正則的一個(gè)字符對應(yīng)一個(gè)字符,我們可以用[]把它們括起來,讓[]這個(gè)整體對應(yīng)一個(gè)字符。如
alert(/ruby/.test( "ruby" ));
alert(/[abc]/.test( "a" ));
alert(/[abc]/.test( "b" ));
alert(/[abc]/.test( "c" ));
alert( "a bat ,a Cat,a fAt bat ,a faT cat" .match(/[bcf]at/gi));
|
負(fù)向類
也是在那個(gè)括號里做文章,前面加個(gè)元字符進(jìn)行取反,表示匹配不能為括號里面的字符。
alert(/[^abc]/.test( "a" ));
alert(/[^abc]/.test( "b" ));
alert(/[^abc]/.test( "6" ));
alert(/[^abc]/.test( "gg" ));
|
范圍類
還是在那個(gè)中括號里面做文章。有時(shí)匹配的東西過多,而且類型又相同,全部輸入太麻煩,我們可以用它。特征就是在中間加了個(gè)橫線。
組合類
還是在那個(gè)中括號里面做文章。允許用中括號匹配不同類型的單個(gè)字符。
alert(/[a-f]/.test( "b" ));
alert(/[a-f]/.test( "k" ));
alert(/[a-z]/.test( "h" ));
alert(/[A-Z]/.test( "gg" ));
alert(/[^H-Y]/.test( "G" ));
alert(/[0-9]/.test( "8" ));
alert(/[^7-9]/.test( "6" ));
|
alert(/[a-m1-5\n]/.test( "a" ))
alert(/[a-m1-5\n]/.test( "3" ))
var a = "\n\
"
alert(/[a-m1-5\n]/.test(a))
alert(/[a-m1-5\n]/.test( "r" ))
|
預(yù)定義類
還是在那個(gè)中括號里面做文章,不過它好像已經(jīng)走到盡頭了。由于是中括號的馬甲,因此它們還是對應(yīng)一個(gè)字符。
字符 | 等同于 | 描述 |
. | [^\n\r] | 除了換行和回車之外的任意字符 |
\d | [0-9] | 數(shù)字字符 |
\D | [^0-9] | 非數(shù)字字符 |
\s | [ \t\n\x0B\f\r] | 空白字符 |
\S | [^ \t\n\x0B\f\r] | 非空白字符 |
\w | [a-zA-Z_0-9] | 單詞字符(所有的字母) |
\W | [^a-zA-Z_0-9] | 非單詞字符 |
alert(/\d/.test( "3" ))
alert(/\d/.test( "w" ))
alert(/\D/.test( "w" ))
alert(/\w/.test( "w" ))
alert(/\w/.test( "司" ))
alert(/\W/.test( "徒" ))
alert(/\s/.test( " " ))
alert(/\S/.test( " " ))
alert(/\S/.test( "正" ))
alert(/./.test( "美" ))
alert(/./.test( " " ))
var a = "\n\
"
alert(/./.test(a))
|
量詞
由于元字符與特殊字符或字符類或者它們的組合(中括號)甚至它們的馬甲(預(yù)定義類)都是一對一進(jìn)行匹配。我們要匹配“司徒正美這個(gè)詞”,最簡單都要/..../,如果長到50多個(gè)字符豈不是要死人。因此我們逼切需要一個(gè)簡單的操作,來處理這數(shù)量關(guān)系。
簡單量詞
代碼 | 類型 | 描述 |
| 軟性量詞 | 出現(xiàn)零次或一次 |
* | 軟性量詞 | 出現(xiàn)零次或多次(任意次) |
+ | 軟性量詞 | 出現(xiàn)一次或多次(至道一次) |
{n} | 硬性量詞 | 對應(yīng)零次或者n次 |
{n,m} | 軟性量詞 | 至少出現(xiàn)n次但不超過m次 |
{n,} | 軟性量詞 | 至少出現(xiàn)n次(+的升級版) |
alert(/..../.test( "司徒正美" ))
alert(/司徒正美/.test( "司徒正美" ))
alert(/[\u4e00-\u9fa5]{4}/.test( "司徒正美" ))
alert(/[\u4e00-\u9fa5]{4}/.test( "司徒正美55" ))
alert(/^[\u4e00-\u9fa5]+$/.test( "正則表達(dá)式" ))
alert(/^[\u4e00-\u9fa5]+$/.test( "正則表達(dá)式&*@@" ))
alert(/\d{6}/.test( "123456" ))
alert(/[ruby]{2}/.test( "rr" ))
alert(/[ruby]{2}/.test( "ru" ))
alert(/[ruby]{2}/.test( "ry" ))
|
/[\u4e00-\u9fa5]/用于匹配單個(gè)漢字。
貪婪量詞,惰性量詞與支配性量詞
貪婪量詞,上面提到的所有簡單量詞。就像成語中說的巴蛇吞象那樣,一口吞下整個(gè)字符串,發(fā)現(xiàn)吞不下(匹配不了),再從后面一點(diǎn)點(diǎn)吐出來(去掉最后一個(gè)字符,再看這時(shí)這個(gè)整個(gè)字符串是否匹配,不斷這樣重復(fù)直到長度為零)
隋性量詞,在簡單量詞后加問號。由于太懶了,先吃了前面第一個(gè)字符,如果不飽再捏起多添加一個(gè)(發(fā)現(xiàn)不匹配,就讀下第二個(gè),與最初的組成一個(gè)有兩個(gè)字符串的字符串再嘗試匹配,如果再不匹配,再吃一個(gè)組成擁有三個(gè)字符的字符串……)。其工作方式與貪婪量詞相反。
支配性量詞,在簡單量詞后加加號。上面兩種都有個(gè)不斷嘗試的過程,而支配性量詞卻只嘗試一次,不合口味就算了。就像一個(gè)出身高貴居支配地位的公主。但你也可以說它是最懶量詞。由于javascript不支持,所以它連出場的機(jī)會(huì)也沒有了。
var re1 = /.*bbb/g;
var re2 = /.*?bbb/g;
alert(re1.test( "abbbaabbbaaabbbb1234" )+ "" );
alert(re1.exec( "abbbaabbbaaabbbb1234" )+ "" );
alert( "abbbaabbbaaabbbb1234" .match(re1)+ "" );
alert(re2.test( "abbbaabbbaaabbbb1234" )+ "" );
alert(re2.exec( "abbbaabbbaaabbbb1234" )+ "" );
alert( "abbbaabbbaaabbbb1234" .match(re2)+ "" );
|
分組
到目前為止,我們只能一個(gè)字符到匹配,雖然量詞的出現(xiàn),能幫助我們處理一排密緊密相連的同類型字符。但這是不夠的,下面該輪到小括號出場了,中括號表示范圍內(nèi)選擇,大括號表示重復(fù)次數(shù)。小括號允許我們重復(fù)多個(gè)字符。
alert(/(dog){2}/.test( "dogdog" ))
alert( "baddad" .match(/([bd]ad?)*/))
alert( "mon and dad" .match(/(mon( and dad)?)/))
|
反向引用
反向引用標(biāo)識由正則表達(dá)式中的匹配組捕獲的子字符串。每個(gè)反向引用都由一個(gè)編號或名稱來標(biāo)識,并通過“\編號”表示法進(jìn)行引用。
var color = "#990000" ;
/ #(\d+)/.test(color);
alert(RegExp.$1);
alert(/(dog)\1/.test( "dogdog" ))
var num = "1234 5678" ;
var newNum = num.replace(/(\d{4}) (\d{4})/, "$2 $1" );
alert(newNum)
|
候選
繼續(xù)在分組上做文章。在分組中插入管道符(“|”),把它劃分為兩個(gè)或多個(gè)候多項(xiàng)。
var reg = /(red|black|yellow)!!/;
alert(reg.test( "red!!" ))
alert(reg.test( "black!!" ))
alert(reg.test( "yellow!!" ))
|
非捕獲性分組
并不是所有分組都能創(chuàng)建反向引用,有一種特別的分組稱之為非捕獲性分組,它是不會(huì)創(chuàng)建反向引用。反之,就是捕獲性分組。要?jiǎng)?chuàng)建一個(gè)非捕獲性分組,只要在分組的左括號的后面緊跟一個(gè)問號與冒號就行了。
var color = "#990000" ;
/ #(?:\d+)/.test(color);
alert(RegExp.$1);
|
題目,移除所有標(biāo)簽,只留下innerText!
var html = "<p><a href='; var text = html.replace(/<(?:.|\s)*?>/g, "" );
alert(text)
|
注意:javascript不存在命名分組
前瞻
繼續(xù)在分組內(nèi)做文章。前瞻與后瞻其實(shí)都屬于零寬斷言,但javascript不支持后瞻。
零寬斷言 |
正則 | 名稱 | 描述 |
(?=exp) | 正向前瞻 | 匹配exp前面的位置 |
(?!exp) | 負(fù)向前瞻 | 匹配后面不是exp的位置 |
(?<=exp) | 正向后瞻 | 匹配exp后面的位置不支持 |
(?<!exp) | 負(fù)向后瞻 | 匹配前面不是exp的位置不支持 |
正向前瞻用來檢查接下來的出現(xiàn)的是不是某個(gè)特定的字符集。而負(fù)向前瞻則是檢查接下來的不應(yīng)該出現(xiàn)的特定字符串集。零寬斷言是不會(huì)被捕獲的。
var str1 = "bedroom" ;
var str2 = "bedding" ;
var reBed = /(bed(?=room))
alert(reBed.test(str1));
alert(RegExp.$1)
alert(RegExp.$2 === "" )
alert(reBed.test(str2))
|
var str1 = "bedroom" ;
var str2 = "bedding" ;
var reBed = /(bed(?!room))/
alert(reBed.test(str1))
alert(reBed.test(str2))
|
題目,移除hr以外的所有標(biāo)簽,只留下innerText!
var html = "<p><a href='; var text = html.replace(/<(?!hr)(?:.|\s)*?>/ig, "" )
alert(text)
|
邊界
一個(gè)要與字符類合用的東西。
邊界 |
正則 | 名稱 | 描述 |
^ | 開頭 | 注意不能緊跟于左中括號的后面 |
$ | 結(jié)尾 | |
\b | 單詞邊界 | 指[a-zA-Z_0-9]之外的字符 |
\B | 非單詞邊界 | |
題目,設(shè)計(jì)一個(gè)字符串原型方法,實(shí)現(xiàn)首字母大寫!
var a = "ruby" ;
String.prototype.capitalize = function () {
return this .replace(/^\w/, function (s) {
return s.toUpperCase();
});
}
alert(a.capitalize())
|
單詞邊界舉例。要匹配的東西的前端或未端不能為英文字母阿拉伯字?jǐn)?shù)字或下橫線。
var str = "12w-eefd&efrew" ;
alert(str.match(/\b\w+\b/g))
|
實(shí)例屬性 | 描述 |
global |
是當(dāng)前表達(dá)式模式首次匹配內(nèi)容的開始位置,從0開始計(jì)數(shù)。其初始值為-1,每次成功匹配時(shí),index屬性都會(huì)隨之改變。 |
ignoreCase |
返回創(chuàng)建RegExp對象實(shí)例時(shí)指定的ignoreCase標(biāo)志(i)的狀態(tài)。如果創(chuàng)建RegExp對象實(shí)例時(shí)設(shè)置了i標(biāo)志,該屬性返回True,否則返回False,默認(rèn)值為False。 |
lastIndex |
是當(dāng)前表達(dá)式模式首次匹配內(nèi)容中最后一個(gè)字符的下一個(gè)位置,從0開始計(jì)數(shù),常被作為繼續(xù)搜索時(shí)的起始位置,初始值為-1,
表示從起始位置開始搜索,每次成功匹配時(shí),lastIndex屬性值都會(huì)隨之改變。(只有使用exec()或test()方法才會(huì)填入,否則為0) |
multiLine |
返回創(chuàng)建RegExp對象實(shí)例時(shí)指定的multiLine標(biāo)志(m)的狀態(tài)。如果創(chuàng)建RegExp對象實(shí)例時(shí)設(shè)置了m標(biāo)志,該屬性返回True,否則返回False,默認(rèn)值為False。 |
source |
返回創(chuàng)建RegExp對象實(shí)例時(shí)指定的表達(dá)式文本字符串。 |
var str = "JS's Louvre" ;
var reg = /\w/g;
alert(reg.exec(str));
alert(reg.lastIndex);
alert(reg.exec(str));
alert(reg.lastIndex);
alert(reg.exec(str));
alert(reg.lastIndex);
alert(reg.exec(str));
alert(reg.lastIndex);
|
|