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