javascript正則表達式

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
發佈了37 篇原創文章 · 獲贊 4 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章