javascript 正則表達式

好久都沒有寫博客了,主要是太懶了,尤其是在陽春三月,風和日麗的日子,太陽暖暖的照在身上,真想美美的睡上一覺。就導致了這篇博客拖到現在纔開始動筆,javascript的正則這一塊也不是什麼新的東西,主要是以前本人一遇到寫正則的需求就開始頭大,頭疼,網上剽竊,東拼西湊,反正就是各種不適應,所以我打算系統的把正則表達式看一遍,一來是自己有所提升,這一塊知識點的查漏補缺,二來是給大家分享一下。好了,下面我們直接進入主題:

  正則是匹配字符串特定模式的一種表達式,官方是這樣說的,但我的理解不外乎就是匹配字符竄嘛,舉個例子大家就明白了。比如我們要驗證郵箱,試想一下如果我們不用正則來匹配,直接用代碼,循環,判斷各種搗鼓來驗證還真是一件非常麻煩的事情。如果用正則怎麼來做了,這裏爲了照顧小白(當然我也是重小白走來的,所以小白很單純,小白很善良,小白很偉大)我就寫僞正則來描述:   所有0-9或者a-z或者A-Z的字符出現一次到多次 加上(就是前面出現了的所有0-9...的字符跟上) "."或者"_"出現0次或者1次,然後在跟上 "@"符號 跟上 xxx.xx這種格式。 不知道我這樣來描述各位親有沒有明白一點,不明白也不要緊,這裏我只是隨便舉個列子,提一下,在下文的某個位置我會專門一步一步分析幾個非常複雜的正則表達讓大家能夠很快的明白正則的語義。

  上面舉了一個郵箱地址的正則表達式,比如這一竄 /^([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+\.[a-zA-Z]{2,3}$/ ;要看懂坑爹的這一竄,還得從基礎一步一步的來。首先給大家介紹javascript經常使用正則的對象和方法:

  RegExp  這個是正則對象, 比如匹配字符串"1234"中的"23"可以這樣玩: (new RegExp("23")).test("1234"); //out true;

  當然正則對象還有一種寫法: var reg = /23/; reg.test("1234")  //out true;

  RegExp.test(String) ;      //這個方法上面的用上了,匹配字符串是否爲指定格式

  RegExp.exec(String);      //返回查詢的值

    var str = "123 aa cat Cat caT";

    var reg = /cat/i;

    reg.exec(str); // out "cat" 如果有則返回,沒有的話就返回null

  String.search(RegExp) ; // 返回索引位置,類似indexOf()

    var data = "123123,213,12312,312,3,Cat,cat,dsfsdfs,";
      var reCat = /cat/gi;
      alert(data.search(reCat));   //out "23"

  String.replace(RegExp, String)//  將字符串替換成另外一個字符竄,RegExp指定的格式,String要替換的字符串

    var str = "1234aa67aa89";
      var reg = /aa/gi;
      str.replace(reg, "") ; //out "12346789"

  String.split(RegExp) ;              // 將字符串拆分成數組

    var str = "1234aa67aa89";
      var reg = /aa/gi;
      str.split(reg) ; //out [1234, 67, 89]

  String.match(RegExp);          //將指定格式的字符串以數組的方式返回

    var data = "123123,213,12312,312,3,Cat,cat,dsfsdfs,";
      var reCat = /cat/gi;
        var arrMactches = data.match(reCat); // out ["Cat", "cat"]

  上面的的方法是在字符串過濾操作中經常用到的方法, 當然還有一些我沒有全部列舉出來,用到了在去差API也不遲,好了我們熟悉了操作正則的這些方法之後我們緊接着正則表達式了,所謂表達式意思就是用一些字符按照先後順序組合在一起表示的一層含義,所以我們先要重正則表達式的元字符說起,其實元字符就相當於javascript語言的關鍵字,比如你定義變量不能這樣幹 var if = "xxxx"; 正則有一下一些元字符:{ [ ^ | $ ] } ? * + . 這些都是正則的元字符,這裏我就不解釋意思了,用到了時候再來分析。如果大家想知道可以找度娘

  字符類

  字符類是用於測試字符串的組合, 將一些字符放入方括號中,就可以有效的告訴正則表達式去匹配第一個,第二個,第三個...比如/[abc]/,這個又稱之爲簡單類

    簡單類

1   var str = "cat 123 caT 234 cAt 345 CaT";2   var reg = /cat/gi;3   str.match(reg) ; //out ["cat", "caT", "cAt", "CaT"]

 

    負向類和範圍類: 這裏要解釋下"^" "-"這兩個符號, "^"這個符號的意思就是取反,而"-"是範圍, g表示全局,i表示忽略大小寫,/[^2-3a-z]+/gi 所以這句話的意思就是: 除了2到3和a到z的所有字符出現1次到多次,並且在全局中忽略大小寫。其實細心的看官這裏還會發現一個知識點, 2-3a-z這一句其實是一個組合,又稱之爲組合類,下面的這個實例就用到了正則的幾個知識點: 1.負向類,意思就是取反; 2. 範圍類; 3.組合類,相當於邏輯運算符的並且&&

1   var str = "cat123caT234cAt345CaT";2   var reg = /[^2-3a-z]+/gi;3   str.match(reg);  //out ["1", "4", "45"]

    預定義類

複製代碼

^\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]            非單詞字符

複製代碼

   量詞:量詞是可以指某個特定模式出現的次數,可以是硬性量詞,比如某個字符出現三次,也可以是軟性量詞,比如某個字符至少出現一次。正則中的量詞有以下這些

  貪婪量詞

  ?      出現零次到一次

  +       至少出現一次或者多次

  *        出現0次到多次

  {n}    出現n次

  {n,m}出現n次到m次

  {n,}   至少出現n次或者n+次

  說道量詞的話有貪婪, 惰性和支配量詞,以上的這些量詞都是貪婪量詞,由於javascript正則引擎對支配量詞支持不是很好,所以我們這裏重點來說貪婪和惰性量詞,先把惰性量詞列出來之後在來說說他們的關係和區別

  惰性量詞

  ??          出現零次到一次

  +?           至少出現一次或者多次

  *?            出現零次到多次

  {n}?          出現n次

  {n,m}?      出現n次到m次

  {n,}?         至少出現n次或者n+次

  貪婪量詞在匹配字符串的時候首先看是否匹配字符串,如果沒有找到匹配的則去掉字符串中最後一個字符再次嘗試,整個過程一直重複,直到字符串爲空時停止。而惰性量詞正好相反,首先查看字符串中第一個字符是否匹配,否則在讀入下一個字符在進行匹配,直至重複這個過程到讀入整個字符竄都不匹配時停止。可能說了這些多還是不太明白,下面我會舉個例子幫助大家理解

1         var str = "abbbaabbbaaabbb1234";2         var re1 = /.*bbb/g;   //貪婪匹配3         var re2 = /.*?bbb/g;  //惰性匹配4         alert(str.match(re1));5         alert(str.match(re2));

  親,你覺得第一個alert會輸出什麼呢,如果是[abb, aabbb, aaabbb]的話的, 那麼恭喜你答錯了,前面說過*是貪婪量詞,它在匹配的時候會首先匹配整個字符串,是從字符串的尾部操作的,當去掉字符1的時候就發現剩下的字符串"abbbaabbbaaabbb"已經達到它匹配的要求了,所以它返回的結果就是字符串"abbbaabbbaaabbb", 而第二個alert爲啥子會打印[abbb,aabbb,aaabbb]呢,我們再來一步一步的看,這個是惰性匹配,所以它在匹配字符串的時候是從字符串開始的部分取出第一個字符進行匹配,發現不行,在取下一個,還是不行,直至取到了"abbb".好,現在發現匹配了,然後將這個裝進數組, 在從剩下的字符串裏面取,直至最後將符合指定模式的子字符串裝進數組,所以最後就返回[abbb,aabbb,aaabbb]。只要稍微花點心思動動手還是很容易就理解了。好了,關於正則的量詞的一些知識點就講到這裏,萬里長征才走一半,下面接到說正則的複雜模式,上面說到的字符類那一塊都是正則的簡單模式,只能做一些簡單的字母,數字,漢字,長度等效驗,如果在掌握了下面的複雜模式就可以非常牛逼的匹配各種複雜,蛋痛的字符串模式了,比如郵箱,***驗證,標籤過濾,包括jquery類選擇器,sizzle引擎過濾器。好了,直接切入主題吧:

複雜分組

  分組模式:分組模式就那麼回事我用一個例子或許你一下子就豁然開朗了

複製代碼

            //如果要匹配"andand"的怎麼做呢,你也許會說可以這樣幹
            var str = "asdfandandcxhksdf";            var reg = /andand/gi;
            alert(reg.test(str)); //output true
            //好的,親,這樣匹配也是可以的,但是有不知道多少and怎麼辦呢,
            //不可能全部加在正則表達式裏面吧,此時分組的便捷性就體現出了
            //出了它的優勢,我們可以這樣幹:
            var reg = /(and){2}/g; //注意這裏()是元字符分組的意思,{2} 是量詞,貪婪量詞

複製代碼

  捕獲分組模式:指的是RegExp.$1這個屬性的值,這個值就是正則中一個分組的值,在這個對象RegExp中,定義了最多支持RegExp.$1-RegExp.$100個分組值,還是來個例子吧

  

1             var str = "asdffirstfirstsecondsecond1234";2             var reg = /(first){2}(second){2}/gi;3             reg.test(str); // 要必須匹配之後纔有下面的值4             alert(RegExp.$1); //output "first"5             alert(RegExp.$2); //output "second"

  非捕獲分組模式:上面說了捕獲分組,那非捕獲分組其實就是不讓RegExp.$1引用了,這裏要說一點的是在捕獲分組中RegExp.$1會創建正則的反向引用的存儲空間,所以在進行捕獲分組時會有更多的空間開銷,還會降低匹配速度。那現在曉得非捕獲分組的好處了吧。簡單的說就是在正則表達式()裏面加上一個問號和冒號/(?:first)/,語法就是這樣的,還是看代碼吧

1             var str = "#123456789";2             var reg = /#(?:\d+)/;3             reg.test(str);4             alert(RegExp.$1);      //output "" 注意這裏取消了反向引用就爲空了

  候選模式:候選我的理解就是或者,舉個例子,比如你要對一個表達式同時匹配"red", "black"的話怎麼做呢, 如果是在以前的話就要寫兩個正則來進行分別匹配,而加入了候選就可以非常方便的操作了,還是上代碼吧

複製代碼

            var str1 = "111red222";            var str2 = "111black111";            var reg = /(red|black)/;
            alert(reg.test(str2)); //output true
            alert(reg.test(str1)); //output true

複製代碼

  前瞻模式:有時候我們希望某個字符分組出現在另外一個字符分組之前纔去捕獲,這相當於是在正則裏面做判斷了, 果然是高級功能,灰常強大,我在寫正則的時候也沒有用到過, 只是書上都說了, 我還是把它搬到這裏來出哈風頭。 上代碼吧

複製代碼

 1         /* 2              *前瞻又分爲正向前瞻和反向前瞻 3              *下面我會用代碼加註釋的方式加以描述 4              */ 5              //正向前瞻 6              var str1 = "bedroom"; 7              var str2 = "bedding"; 8              var reg = /(bed(?=room))/; //符號?=來表示正向前瞻,表示在字符串"bedroom"中如果bed後面有room的字符才捕獲,順序執行 9              alert(reg.test(str1)); //output true10              alert(RegExp.$1);      //output "bed" 捕獲到反向引用bed字符串11              alert(reg.test(str2)); //output true12              //反向前瞻13              var reg = /(bed(?!ing))/; //符號?!來表示反向前瞻,表示在字符串"bedding"中如果有"ing"子字符串才捕獲,逆序執行14              alert(reg.test(str2)); //output true15              alert(RegExp.$1);      //output "bed" 捕獲到反向引用bed字符串16              alert(reg.test(str1)); //output true17              alert(RegExp.$1);18              /*以上代碼如果各位親測試不通過的話那就是正則引擎不支持前瞻*/

複製代碼

  邊界模式:這個模式很重要也很常用,比如去掉字符串的首尾空格,那下面說說幾種邊界的可能:

  ^行的開始           $行的結尾             \b單詞的邊界               \B非單詞的邊界

複製代碼

            //用一個例子來說明邊界
            var str = "  xiaoming     "            var reg = /(^\s+)|\s+$/g; //(^\s+)去除字符串開始位置的空格,\s+$去除字符串尾部空格,|這個符號想必不用我說了吧,候選
            var str = str.replace(reg, "");
            alert(str); //output "xiaoming"

複製代碼

  多行模式:這個也是正則複雜模式裏面最後一個模式了,也不經常用,不管你信不信,反正我是信了,還是直接來看代碼吧

複製代碼

1             //請看下面這個實例,\n在前面的預定類,表示換行2             var str = "first\nsecond\nthread";3             var reg = /^(\w+)/g;  
4             alert(str.match(reg)); //output 若不指定m行的話就輸出"first"5             var reg = /^(\w+)/gm;6             alert(str.match(reg)); //output [first, second, thread]

複製代碼

  到目前爲止正則表達式的語法,規則各種都已經說完了,如果各位小白認真的看到這裏,我們在來分析文章開頭說的郵箱驗證表達式就非常容易了。好,現在我們就來一步一步的分析那個非常蛋痛的表達式,首先我們要來拆分這段表達式,我會用不同的顏色來表示這段表達式的每一段,這裏就用到了一種思想,分而治之,太複雜的東西不利於直觀的表達某些東西,所以拆分,打碎,各個擊破:

  /^([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+\.[a-zA-Z]{2,3}$/

  1.([a-zA-Z0-9]+[_|\_|\.]?)* 這一段表示的是一個分組,分組()裏面首先是[a-zA-Z0-9]意思是匹配字符串大小寫字母數字,後面緊跟一個+,這個是貪婪量詞,1次到多次,前面提到過的。[a-zA-Z0-9]+而這一段的意思就是說大小寫字母數字匹配1次到多次,[_|\_|\.]?而這個呢是符號"_"或者"."出現0次到一次。整個這段表達式的意思就是所有大小寫字母數字出現1次到多次,緊接着符號"_"和"."出現0次到一次,在把這兩個條件加起來成爲一個組,這個組的格式又可以出現0次到多次。

  2.[a-zA-Z0-9]+ 這段就不用說了吧,上面也說了就是大小寫字符數字出現1次到多次

  3.@([a-zA-Z0-9]+[_|\_|\.]?)* 這個理解起來就簡單了,以字符@開頭上面那個分組出現0次到多次的這個格式

  4.\.[a-zA-Z]{2,3}  這個表達式呢還是比較容易,也是以字符"."開頭所有大小寫字母出現兩次或者三次

  5./^$/ 這兩個符號是表示從字符串的開始匹配到行的結束。

  看到這裏大家是不是對正則表達式的認識更深了一些呢, 如果還不行話在給大家分析一個實例吧 /^((0?[1-9])|((1|2)[0-9])|30|31)$/ 這個正則的意思是驗證一個月的31天,正確格式是01、09和1、31。首先我們還是來拆分 /^((0?[1-9])|((1|2)[0-9])|30|31)$/

  1.首先這個表達式中出現了三個黑色的"|"候選符號,意思就是說可以匹配四種情況

  2.(0?[1-9]) 這個表達式是匹配 0出現0次或者一次緊接着跟上數字出現一次,這是一種情況,如:01, 09, 1, 9這些

  3.((1|2)[0-9]) 這個分組表示的是1或者2出現一次緊接着跟上0-9出現一個,又是一種情況,如:10,19,20,29

  4.30|31 這個就更簡單了,30或者31只能出現一次。

轉自:http://www.cnblogs.com/ghostgift/archive/2013/03/28/2980406.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章