JavaScript中的正則表達式(終結篇)
在之前的幾篇文章中,我們了解了正則表達式的基本語法,但那些語法不是針對於某一個特定語言的。這篇博文我們將通過下面幾個部分來了解正則表達式在JavaScript中的使用:
第一部分:JavaScript對正則表達式的支持程度
之前我介紹了正則表達式的基本語法,如果大家不是很了解可以先看下面幾篇文章:
但是ECMAScript並沒有支持上述正則表達式的所有功能,尤其是缺少一些語言所支持的高級正則表達式特性。下面的這些都是JavaScript所不支持的:
- 匹配字符串開始和結尾的\A和\Z錨。(但我們仍可以使用^和$來匹配字符串的開始和結尾)
- 向后查找(lookbehind)(注:但是JavaScript完全支持向前查找(lookahead))
- 並集和交集類
- 原子組(atomic grouping)
- Unicode支持(單個字符除外,如\uFFFF)
- 命名的捕獲組
- s(single,單行)和x(free-spacing,無間隔)匹配模式
- 條件匹配
- 正則表達式注釋
更多關於JavaScript對正則表達式支持的內容可以點擊這里。
第二部分:支持正則表達式的RegExp類型
JavaScript是通過RegExp類型來支持正則表達式的。而創建RegExp類型有兩種方法。一種是字面量方法(類似於Perl的語法),另一種是使用JavaScript的RegExp構造函數,下面將逐一介紹。
1.字面量方法
var expression = /pattern/flags;
其中expression即為正則表達式的名稱,模式(pattern)可以是任何復雜或簡單的正則表達式(但必須是在JavaScript支持范圍內的),標志(flags)即用來表明正則表達式行為。
下面介紹JavaScript中支持的三個標志(flags):
- g: 表示全局(global)模式,表示pattern會應用於所有字符串,而不是找到一個匹配項后立即停止。
- i :表示不區分大小寫(ignore)模式。即忽略pattern和字符串的大小寫。
- m:表示多行(multiple)模式。 即到一行文本末尾時還會繼續查找下一行中是否存在匹配的項。
說明:在字面量方法中的flags可以是g、i、m中的任意一個或幾個且這里的標志完全適用於之后要講的RegExp構造函數方法。
舉例:
var pattern=/at/gi;
此字面量形式的正則表達式表示在不區分大小寫的情況下在全局范圍內匹配at。
2.RegExp構造函數法
var pattern = new RegExp("pattern","flags");
即這種方法使用了RegExp構造函數,並且傳遞了兩個參數(同字面量方法),但值得注意的是:pattern(模式)和flags(標志)都需要使用引號括起來。
3.對模式中的元字符轉義的方法
當我們希望使用元字符本身的含義時,我們就需要對元字符進行轉義。比如[ab]c表示ac或bc;若通過\轉義,即\[ab\]c就表示成了[ab]c。但是對於上述兩種不同的創建方法有不同的轉義方式。
首先,請記住在JavaScript中的元字符有 ( [ { \ ^ $ | ) ? * + . ] ) }。
使用字面量方法創建正則表達式轉義:在需要轉義的正則表達式前加\即可。如var pattern = /\[ab\]c/g;表示在全局范圍內匹配abc
使用RegExp構造函數創建正則表達式轉義:在需要轉義的正則表達式前加\\。如var pattern = RegExp("\\[ab\\]c","g");同樣表示在全局范圍內匹配abc
4.舉例
如果希望知道字符串XxxxoOoooommmm中o的數量(不區分大小寫),這時就可以使用match方法傳入字符串,如:
var string = "XxxxoOoooommmm"; console.log(string.match(/o/ig).length);
輸出為6,這種方法還是很容易的。
第三部分:RegExp的實例屬性
無論是何種方法創建的正則表達式,他們都具有下面幾種屬性來描述有關模式的信息:
- global---表示flags(標志)中是否設置了g標志。
- ignoreCase---表示flags(標志)中是否設置了i標志。
- lastIndex---表示開始搜索下一個匹配項的字符位置的整數,從0算起。
- multiple---表示flags(標志)中是否設置了m標志。
- source---按照字面量形式返回正則表達式的字符串表示。
舉例如下所示:
// var pattern = RegExp("\\[ba\\]at","gi");//使用RegExp構造函數創建得到的效果和下面使用的字面量方法創建得到的效果相同 var pattern = /\[ba\]at/gi; console.log(pattern.global); //true console.log(pattern.ignoreCase); //true console.log(pattern.multiline); //ture console.log(pattern.lastIndex); //0 console.log(pattern.source); // \[ba\]at
當然,上面代碼中使用了大量的console.log()顯得很復雜,也可以將這5個屬性作為5個參數直接傳入到console.log()中。如下所示:
var pattern = /\[ba\]at/gi; console.log(pattern.global,pattern.ignoreCase,pattern.multiline,pattern.lastIndex,pattern.source); //true true false 0 "\[ba\]at"
我們還可以將這5個屬性保存在一個數組中,再通過console.log()直接輸出數組,如下所示:
var pattern = /\[ba\]at/gi; var properties=[pattern.global,pattern.ignoreCase,pattern.multiline,pattern.lastIndex,pattern.source]; console.log(properties);
在控制台中可以看到:
第四部分:RegExp的實例方法
RegExp的實例主要有兩個方法exec()和test(),並且還有從Object繼承的toString()和toLocaleString()方法,下面將會逐一介紹。
1.RegExp實例的exec()方法
這個方法接收一個參數,即要應用模式的字符串,用於捕獲組。
如果匹配,則返回一個數組;否則返回null。
且其中返回的數組還有額外的兩個方法:index和input。index表示匹配項在字符串中的位置,input表示應用正則表達式的字符串。
舉例如下所示:
var text="mom and dad and baby"; var pattern=/mom( and dad( and baby)?)?/gi; var matches=pattern.exec(text); console.log(matches);
如果匹配不了,則matches為null;如果匹配,將會在控制台中輸出一個數組,如下所示:
我們可以看到,數組中包含三個元素,分別是matches[0]、matches[1]和matches[2]。並且在數組中還有一個index屬性為0,表示匹配項在字符串中的位置為0,即在開始處就匹配上了。 而input屬性是text字符串。
2.RegExp實例的test()方法
這個方法同樣也接收一個字符串,如果pattern(模式)和字符串匹配,則返回true,否則返回false。
並且test()方法經常被用在if語句中,舉例如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Regular Expression</title> </head> <body> <input type="text" id="phoneNumber"> <button id="submit">提交</button> <script> window.onload=function(){ var btn=document.getElementById("submit"); btn.onclick=function(){ var phoneNumber=document.getElementById("phoneNumber").value; var pattern=/1[358]\d{9}/gi; if(pattern.test(phoneNumber)){ alert("Yes! Your phoneNumber is legal"); }else{ alert("No!Your phoneNumber is illegal"); } } } </script> </body> </html>
這個小demo可以判斷用戶輸入的手機號碼是否合法,並給出響應提示,演示如下:
3.RegExp實例的toString()和toLocalString()方法
這兩個方法都會返回正則表達式的字面量,與創建正則表達式的方式無關。
舉例如下:
var pattern=/1[358]\d{9}/gi; console.log(pattern.toString()); console.log(pattern.toLocaleString());
在控制台中我們可以看到效果如下所示:
第五部分:RegExp的構造函數屬性
RegExp構造函數也包含了一些屬性。值得注意的是,這些屬性有兩種方式來訪問---長屬性名和短屬性名。介紹如下:
- input $_ 最近一次要匹配的字符串 。(注意:前者是長屬性名,后者是短屬性名,下同)
- lastMatch $& 最近一次的匹配向。
- lastParen $+ 最近一次匹配的捕獲組。
- leftContext $` input字符串中lastMatch之前的文本
- RightContext $' input字符串中lastMatch之后的文本
- multiline $* 布爾值,表示是否所有表達式都使用多行模式
注意:Opera不支持上面的1236對應的四個屬性,IE不支持multiline屬性。
舉例如下所示:
var text="this has been a short summer"; var pattern=/(.)hort/g; if(pattern.test(text)){ console.log(RegExp.input);//this has been a short summer console.log(RegExp.leftContext);//this has been a console.log(RegExp.rightContext);//summer console.log(RegExp.lastParen);//s console.log(RegExp.lastMatch);//short console.log(RegExp.multiline);//undefined }
第六部分:簡單的應用
1.用戶名和密碼驗證
需求如下:
- 用戶名輸入:必須為長度在5~20之間的英文字母,否則提交后報錯。
- 密碼輸入:必須是數字和字母結合,且長度必須為8,否則提交后報錯。
實現思路:
- 用戶名和密碼是否同時正確,正確顯示“成功”。
- 用戶名錯誤,密碼正確,則顯示“用戶名有誤,請重新輸入...”
- 用戶名正確,密碼錯誤,則顯示“密碼有誤,請重新輸入...”
- 用戶名和密碼都錯誤,則顯示“用戶名和密碼均輸入有誤!!!”
代碼如下所示:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Regular Expression</title> <style> input{box-sizing: border-box;padding:10px;width: 300px;height: 50px;line-height: 50px;} input[type="submit"]{height: 30px;line-height: 30px;padding:0;} </style> </head> <body> <form action=""> <input type="text" id="username" placeholder="請輸入長度在5~20之前的英文名稱..." ><br> <input type="password" id="password" placeholder="請輸入長度為8的數字和英文組成的密碼..."><br> <input type="submit" id="submit" value="提交"> </form> <script> window.onload=function(){ var btn=document.getElementById("submit"); btn.onclick=function(){ event.preventDefault(); var username=document.getElementById("username"); var password=document.getElementById("password"); var usernamePattern=/[a-zA-Z]{5,20}/g; var passwordPattern=/[\da-zA-Z]*((\d+[a-zA-Z]+)|([a-zA-Z]+\d+))[\da-zA-Z]*/g; if(usernamePattern.test(username.value)&&(passwordPattern.test(password.value)&&(password.value.length==8))){ alert("成功!"); }else if((!usernamePattern.test(username.value))&&(passwordPattern.test(password.value)&&(password.value.length==8))){ alert("用戶名輸入有誤!請重新輸入..."); }else if((!(passwordPattern.test(password.value)&&(password.value.length==8)))&&usernamePattern.test(username.value)){ alert("密碼輸入有誤!請重新輸入..."); }else{ alert("用戶名和密碼均輸入有誤!!!"); } } }; </script> </body> </html>
關鍵在於判斷輸入的准確與否,這里我使用的是與運算。如當密碼輸入正確,用戶名錯誤時在用戶名的判斷代碼前取非即可,其他同理。
效果如下:
ok,這篇博文就到這里啦,如果覺得不錯,就推薦一下吧!
第七部分:需要注意的地方
1. 之前我們提到過test方法,該方法確實行之有效,但是使用起來還是需要注意一些地方。
比如我要驗證一個手機號,那我可以使用 /1[3-8]\d{9}/.test(18212345678)這個一定是返回true的,但是如果我在電話后面不小心多寫了一個0,即/1[3-8]\d{9}/.test(18212345678) 這個同樣也會返回true,因為test如果只是檢測到存在,就說明true,所以這時比較好的解決辦法就是加$,如 /^1[3-8]\d{9}$/.test(18212345678) 就非常奏效了。
2. 正則表達式中匹配的都是字符串,並且我們知道表單中的value也都是字符串。
注:原創文章,如需轉載,請注明出處。博客地址:http://www.cnblogs.com/zhuzhenwei918/p/6204445.html
千淘萬漉雖辛苦,吹盡狂沙始到金。