1、RegExp 簡介
RegExp 即正則表達式(Regular Expression,在代碼中常簡寫為 regex、regexp或RE/re/reg),就是使用單個字符串來描述、匹配一系列符合某個句法規則的字符串搜索模式,搜索模式可用於文本搜索和文本替換。
正則表達式是由一個字符序列形成的搜索模式,當你在文本中搜索數據時,你可以用搜索模式來描述你要查詢的內容,也就是說正則表達式是描述字符模式的對象,可用於對字符串模式匹配及檢索替換,是對字符串執行模式匹配的強大工具。
所謂正則表達式,直接可理解為規則或者模式表達式,就是表達了某一種計算機可以理解的規則,而一般人很難讀懂的文字表達方式,可用於所有文本搜索和文本替換的操作,簡單說就是處理字符串。
2、字符串方法
(1)、charAt() 獲取某個字符,返回字符串某一位的字符。
(2)、split() 分割字符串,獲得數組。
(3)、search() 查找某個字符首次出現的位置,配合正則使用更好,返回值為數值,沒找到返回-1。
(4)、match() 查找字符串中指定字符並返回該字符,如果不使用正則,則只返回首次出現的指定字符,不會再向後匹配,如果使用正則並進行全局匹配,則以數組形式返回字符串中所有指定的字符,沒找到則返回null。
(5)、replace() 替換字符,返回一個新字符串,配合正則使用更好,可以替換所有匹配。
<script> var str = 'abcdefgca'; //返回字符串中某一位的字符。 alert(str.charAt(3)); //返回:d //查找字符串首次出現的位置。 alert(str.search('z')); //返回:-1 //查找指定的字符。 //只返回第一次出現的c,不再向後匹配。 alert(str.match('c')); //返回:c //將'a'替換為'i'。 //只替換了第一個位置的a,不再向後匹配。 alert(str.replace('a', 'i')); //返回:ibcdefgca //分割字符串。 var str1 = '12-56-aaa-89-cd'; var arr = str1.split('-'); //返回:12,56,aaa,89,cd alert(arr); </script>
實例:使用普通方法找出字符串中所有數字
實現思路:要找出字符串中的數字,其實也不難,使用判斷先將字符串中的數字提取出來,那麼字符串中肯定不止一個數字,所以就需要一個空字符串來存儲提取出來的數字字符,然後再將這些數字字符添加到數組中,最後返回,這樣就完成了。來看看程序是怎麼實現的:
<script> var str = '12 abc 3d4 aa56 78c9 21zz -=-=889s-'; var arr = []; var num = ''; //首先循環遍歷字符串 for(var i=0; i<str.length; i++){ //再判斷當前字符大於等於0並且小於等於9,則為數字 if(str.charAt(i)>='0' && str.charAt(i)<='9'){ //那麼就將當前的字符存儲在空字符串中 num += str.charAt(i); } else{ //如果字符串中有值。 if(num){ //將值添加到數組中。 arr.push(num); //再清空字符串,避免重復添加。 num=''; } } } //最後在整個字符串結束之後有可能還會有數字,再做一次判斷。 if(num){ //如果還有值就添加到數組中。 arr.push(num); //再清空字符串。 num = ''; } //返回:OK,現在返回就完成了。 alert(arr); //返回:12,3,4,56,78,9,21,889 </script>
雖然可以使用普通方法完成,結構清晰,但是代碼相對較長,如果使用正則,那麼一個表達式就完成了這麼多工作,非常方便,下面就來看看怎麼使用正則。
3、使用正則
正則表達式語法:var re = new RegExp('模式', '修飾符');
模式就是表達式的模式,而修飾符是用於指定全局匹配、不區分大小寫等,完整形態就是正則表達式。
看到正則語法長這模樣,不就是 JS 中典型的新創建對象的語法麼,對了,就是新創建一個正則對象。我們都知道,要盡量避免使用 new 關鍵詞,使用 new 無疑就是新創建了一個對象,那麼同時就預示著其占據了一定的內存空間,如果處理不當,積累多了會造成內存溢出,這樣相當耗費資源,不利於代碼優化的實現。同時這樣的寫法,體現不出正則的強大,他應該是很簡潔的才對,因此在實際使用的時候都不采用這種 JS 風格的正則語法,都使用的是另一種風格,如下:
語法:var re = /模式/修飾符;
這種風格就相對簡潔了,屬於一般人看不懂的表達方式。
(1)、修飾符
修飾符用於執行全局匹配和區分大小寫。
忽略大小寫:i (ignore的簡寫,中文翻譯為:忽視)
全局匹配:g (global的簡寫,中文翻譯為:全部的/全局的)
實例:全局搜索指定字符
<script> var str = 'AbCdEFgiX'; //JS風格: //這個正則表達式什麼也不代表,只代表abc本身。 var reg = new RegExp('abc', 'i'); alert(str.match(reg)); //返回:AbC //常用風格: var re = /efg/i; alert(str.match(re)); //返回:EFg </script>
4、方括號和元字符
(1)、方括號
方括號用於查找某個范圍內的字符。
①、任意字符
表達式:[abc]
查找方括號中的任意字符。
[] 在這裡為或的意思,即隨便出現哪個都行。
<script> var str = 'apc xpc ppc bpc spc opc'; //[apx]pc,隨便出現哪個都行,即:apc ppc xpc var re = /[apx]pc/g; alert(str.match(re)); //返回前3個pc。 </script>
②、范圍查找
表達式:[0-9] [a-z] [A-z] [A-Z]
[0-9] 查找任意 0 - 9 的數字。
[a-z] 查找任意 a - z 的字符。
[A-z] 查找任意 大寫A - 小寫z 的字符。
[A-Z] 查找任意 大寫A - 大寫Z的字符。
③、排除查找
表達式:[^abc] [^a-z] [^0-9]
[^abc] 查找任意不在方括號中的字符。
[^a-z] 查找任意除了字母以外的字符,包括數字符號中文外文。
[^0-9] 查找任意除了數字以外的字符,包括字母符號中文外文。
<script> var str = 'o1t out o.t o t o`t ot2 3ot'; //o和t中間除了數字,什麼都可以 var re = /o[^0-9]t/g; alert(str.match(re)); //返回:out,o.t,o t,o`t </script>
④、選擇查找
表達式:(a|b|c)
查找任何指定的選項,a 或 b 或 c。
⑤、匹配還可以使用組合模式,比如:[a-z0-9A-Z] [^a-z0-9]
[a-z0-9A-Z] 任意大小寫字母和數字。
[^a-z0-9] 除了字母和數字以外,什麼都可以。
(2)、元字符
元字符是擁有特殊含義的字符,也可以叫做轉義字符。
下面是一些常用的元字符:
元字符 描述 使用 . 查找單個字符,代表任意字符,不包括換行和行結束符。 不建議使用,容易出問題。 \w 查找單詞字符,包括英文數字下劃線,相當於[a-z0-9] /\w/ \W 查找非單詞字符,相當於[^a-z0-9] /\W/ \d 查找數字,相當於[0-9] /\d/ \D 查找非數字,相當於[^0-9] /\D/ \s 查找空白字符,包括空格符、回車符、制表符、換行符和換頁符,不可顯示不可打印的字符。 /\s/ \S 查找非空白字符。 /\S/ \b 查找位於單詞的開頭或結尾的匹配,如果未匹配到,則返回null。 /\b/ \B查找非單詞邊界的匹配,也就是不位於開頭或結尾,匹配位置的上一個和下一個字符的類型是相同的:即必須同為單詞,
或必須同為非單詞,字符串的開頭和結尾處被視為非單詞字符,如果未匹配到,則返回null。
/\B/ \n 查找換行符,如果找到則返回該位置,如果未找到則返回-1。 /\n/ \f 查找換頁符。 /\f/ \r 查找回車符。 /\r/ \t 查找制表符。 /\t/
5、量詞
所謂量詞,就是數量詞,即個數,用在正則中,表示出現的次數。
下面是一些常用的量詞:
量詞 描述 使用 * 零次或任意次,相當於{0,} 不推薦使用,范圍太廣,不夠精確。 ? 零次或一次,相當於{0, 1} /10?/g 對1進行全局搜索,包括其後緊跟的零個或1個'0'。
下面是一些常用的匹配模式:
模式 描述 使用 ^a 任何開頭為 a 的字符,表示行首 /^\d/ 以數字開頭 /^a/g 全局搜索以'a'開頭的字符 a$ 任何結尾為 a 的字符,表示行尾 /\d$/ 以數字結尾 /z$/g 全局搜索以'z'結尾的字符 ?=a 任何其後緊跟 a 的字符 /a(?= b)/g 全局搜索'a'後緊跟'b'的字符 ?!a 任何其後沒有緊跟 a 的字符 /c(?= d)/g 全局搜索'c'後沒有緊跟'd'的字符
6、字符串和正則配合
(1)、search() 配合正則
實例:找出字符串中第一次出現數字的位置
<script> var str = 'asdf 34 21 zxcvbnm'; //元字符\d,表示轉義為數字 var re = /\d/; alert(str.search(re)); //返回:5 第一個數字為3出現在第5位 </script>
(2)、match() 配合正則
其實沒有什麼東西是非正則不可的,只是正則可以讓做東西更方便。下面就完成本章遺留的歷史問題,怎麼使用正則,能一句代碼就完成普通方法需要很多行代碼才能完成的東西。
在實例之前,先看看 match() 與正則的配合。
<script> var str = 'as8d99999f 34 21 zxcv567m'; //找出字符串中的數字可以使用元字符\d var re = /\d/; //沒告訴系統要找多少數字,系統在找到數字後就返回 alert(str.match(re)); //返回:8 //因此需要全局匹配,使用修飾符g var re = /\d/g; //沒告訴系統要找幾位,系統會將所有找到的數字返回 alert(str.match(re)); //返回:8,9,9,9,9,9,3,4,2,1,5,6,7 //所以可以使用兩個元字符,告訴系統要找的數字是2位 var re = /\d\d/g; //顯然這樣是不可取的,因為數字的位數並不固定,可能是1位,有可能還是多位 alert(str.match(re)); //返回:99,99,34,21,56 //所以需要用到量詞+,+代表若干,也就是多少都可以。 var re = /\d+/g; //現在返回正確。 alert(str.match(re)); //返回:8,99999,34,21,567 </script>
實例:使用正則找出字符串中所有數字
<script> var str = '12 abc 3d4 aa56 78c9 21zz -=-=889s-'; //alert(str.match(/\d+/g)); //元字符\d也可以使用[0-9]代替,0到9隨便哪個都行。 alert(str.match(/[0-9]+/g)); //返回:12,3,4,56,78,9,21,889 </script>
正則是強大的字符串匹配工具,就這樣簡單的使用一句代碼就完成了。
(3)、replace() 配合正則
<script> var str = 'abc zaaz deaxcaa'; //將字符串中的a替換為數字0 alert(str.replace('a', 0)); //僅僅只將第一個a替換為0 //配合正則使用匹配所有a再替換 var re = /a/g; alert(str.replace(re, '0')); //返回所有的a都為0 </script>
實例:簡單的敏感詞過濾
所謂的敏感詞,就是法律不允許的詞語,一切非法詞都可以叫做敏感詞,這包括的范圍就太廣了,比如危害國家安全,反對憲法確立的基本原則,散步謠言,擾亂民心,擾亂社會秩序,破壞社會穩定,色情、暴力、賭博、虛假、侵害、騷擾、粗俗、猥亵或其他道德上令人反感的詞,以及含有法律規定或禁止的其他內容的詞語等。在平時最常見也是大多數人都會用的詞莫屬道德上令人反感的詞了,說斯文一點就是吵架時用於攻擊別人的詞語。這裡就列舉幾個熱門的網絡詞語作為例子。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>JavaScript實例</title> <script> window.onload = function (){ var oBtn = document.getElementById('btn1'); var oTxt1 = document.getElementById('txt1'); var oTxt2 = document.getElementById('txt2'); oBtn.onclick = function (){ //這裡的|在正則中表示 或 的意思 var re = /元芳|萌萌哒|然並卵|毛線|二貨|城會玩/g; //文本框2的值等於文本框1的值過濾掉敏感詞 oTxt2.value = oTxt1.value.replace(re,'***'); }; }; </script> </head> <body> <textarea id="txt1" rows="10" cols="40"></textarea><br> <input id="btn1" type="button" value="過濾"><br> <textarea id="txt2" rows="10" cols="40"></textarea> </body> </html>
可在第一個文本框中輸入一些相關語句,點擊過濾按鈕,查看過濾後的效果。
此外,支持正則表達式的 String 對象的方法還包括 split() 方法,可把字符串分割為字符串數組。
7、RegExp 對象方法
在 JS 中,RegExp 對象是一個預定義了屬性和方法的正則表達式對象。
(1)、test()
test() 方法用於檢測一個字符串是否匹配某個模式,也就是檢測指定字符串是否含有某個子串,如果字符串中含有匹配的文本,返回 true,否則返回 false。
語法:RegExpObject.test(str)
調用 RegExp 對象 re 的 test() 方法,並為它傳遞字符串 str,與這個表示式是等價的:(re.exec(str) != null)。
實例:搜索字符串是否含有指定的字符
<script> var str = 'The best things in life are free, like hugs, smiles, friends, kisses, family, love and good memories.'; var re = /i/; alert(re.test(str)); //返回:true var reg = /z/; alert(reg.test(str)); //返回:false //上面的代碼可以不用定義正則的變量,直接使用,將兩行合並為一行。 alert(/i/.test(str)); alert(/z/.test(str)); </script>
(2)、exec()
exec() 方法用於檢索字符串中的正則表達式的匹配,提取指定字符串中符合要求的子串,該方法返回一個數組,其中存放匹配的結果。如果未找到匹配,則返回 null。可以使用循環提取所有或者指定 index 的數據。
語法:RegExpObject.exec(str)
exec() 方法的功能非常強大,它是一個通用的方法,可以說是 test() 方法的升級版,因為他不僅可以檢測,而且檢測到了可以直接提取結果。該方法使用起來比 test() 方法以及支持正則表達式的 String 對象的方法更為復雜。
<script> var str = 'good good study day day up'; var re = /good/; var arr = re.exec(str); console.log(arr); //控制台顯示:["good"]點開後顯示:0 "good",index 0,input "good good study day day up"。 console.log(arr.index); //控制台顯示:0 console.log(arr.input); //控制台顯示:good good study day day up </script>
通過上面的實例,可以看到,如果 exec() 找到了匹配的文本,則返回一個結果數組。否則,返回 null。此數組的第 0 個元素是與正則表達式相匹配的文本,第 1 個元素是與 RegExpObject 的第 1 個子表達式相匹配的文本(如果有的話),第 2 個元素是與 RegExpObject 的第 2 個子表達式相匹配的文本(如果有的話),以此類推。
除了數組元素和 length 屬性之外,exec() 方法還返回兩個屬性。index 屬性聲明的是匹配文本的第一個字符的位置。input 屬性則存放的是被檢索的字符串 string。我們可以看出,在調用非全局的 RegExp 對象的 exec() 方法時,返回的數組與調用方法 String.match() 返回的數組是相同的。
什麼是"與子表達式相匹配的文本"?
所謂的子表達式就是正則表達式中包含在圓括號中的內容。看下面實例:
<script> var str = 'good good study day day up'; var re = /g(o+)d/; var arr = re.exec(str); console.log(arr); //顯示:["good", "oo"]點開後顯示:0 "good", 1 "oo", index 0,input: "good good study day day up" console.log(arr.length); //顯示:2 var reg = /(o+)/; //var reg = /o+/; 只返回一個"oo",長度為1 var arr1 = reg.exec(str); console.log(arr1); //顯示:["oo", "oo"]點開後顯示:0 "oo", 1 "oo", index 1,input: "good good study day day up" console.log(arr1.length); //顯示:2 </script>
通過上例,可以看到,子表達式是一個大的表達式的一部分,並且必須用()包含起來。一個表達式可使用多個子表達式,同時還支持多層嵌套,把一個表達式劃分為多個子表達式的目的是為了把那些子表達式當作一個獨立的元素來使用。也就是說表達式中的子表達式可以作為整個表達式返回,也可以作為一個單獨的表達式返回。所以上面的數組長度為 2。
使用子表達式是為了提取匹配的子字符串,表達式中有幾個 () 就有幾個相應的匹配字符串,順序會依照 () 出現的順序依次進行,並且 () 中可以使用 或"|" 進行多個選擇。也就是說可以使用 () 對字符進行分組,並保存匹配的文本。
如果該方法使用全局匹配,則找到第一個指定字符,並存儲其位置,如果再次運行 exec(),則從存儲的位置(lastIndex)開始檢索,並找到下一個指定字符,存儲其位置。lastIndex 屬性是 RegExp 對象屬性,是一個整數,標示開始下一次匹配的字符位置。看下面實例:
<script> var str = 'good good study day day up'; var re = /good/g; var arr; do{ arr = re.exec(str); console.log(arr); console.log(re.lastIndex); } while(arr !== null) /* 結果如下: 顯示:["good"],點開後:0 "good", index 0, input "good good study day day up"。 lastIndex為4。 顯示:["good"],點開後:0 "good", index 5, input "good good study day day up"。 lastIndex為9。 顯示:null lastIndex為0。 */ </script>
在調用非全局的 RegExp 對象的 exec() 方法時,返回的數組與調用 String.match() 返回的數組是相同的。但是,當 RegExpObject 是一個全局正則表達式時,exec() 的行為就稍微復雜一些。它會在 RegExpObject 的 lastIndex 屬性指定的字符處開始檢索字符串 string。當 exec() 找到了與表達式相匹配的文本時,在匹配後,它將把 RegExpObject 的 lastIndex 屬性設置為匹配文本的最後一個字符的下一個位置。這就是說,可以通過反復調用 exec() 方法來遍歷字符串中的所有匹配文本。當 exec() 再也找不到匹配的文本時,它將返回 null,並把 lastIndex 屬性重置為 0。
通過上面實例,可以看到,當第三次循環時,找不到指定的 "good",於是返回 null,lastIndex 值也變成 0 了。找到的第一個 "good" 的 lastIndex 值為 4,是匹配文本最後一個字符的下一個位置。
<script> var str = 'good good study day day up'; var re = /good/g; var arr; while((arr = re.exec(str)) != null){ console.log(arr); console.log(re.lastIndex); } /* 結果如下: 顯示:["good"],點開後:0 "good", index 0, input "good good study day day up"。 lastIndex為4。 顯示:["good"],點開後:0 "good", index 5, input "good good study day day up"。 lastIndex為9。 */ </script>
這裡需要注意,如果在一個字符串中完成了一次模式匹配之後要開始檢索新的字符串(仍然使用舊的re),就必須手動地把 lastIndex 屬性重置為 0。
無論 RegExpObject 是否是全局模式,exec() 都會把完整的細節添加到它返回的數組中。這就是 exec() 與 String.match() 的不同之處,後者在全局模式下返回的信息要少得多。因此可以這麼認為,在循環中反復地調用 exec() 方法是唯一一種獲得全局模式的完整模式匹配信息的方法。
(3)、compile
compile() 方法用於在腳本執行過程中編譯正則表達式,也可用於改變和重新編譯正則表達式。主要作用是改變當前(re)匹配模式。
語法:RegExpObject.compile(模式, 修飾符)
模式就是正則表達式,修飾符用於規定匹配的類型,g 匹配全局,i 忽略大小寫,gi 全局匹配忽略大小寫。
該方法是改變匹配模式時使用的,一般情況下,能用到的地方很少。
實例:在全局中忽略大小寫 搜索"day",並用 "天" 替換,然後通過 compile() 方法,改變正則表達式,用 "日" 替換 "Today" 或 "day"。
<script> var str = 'Today is a beautiful day, Day day happy!'; var re = /day/gi; var str1 = str.replace(re, '天'); console.log(str1); //輸出:To天 is a beautiful 天, 天 天 happy! reg = /(to)?day/gi; reg.compile(reg); str1 = str.replace(reg, '日'); console.log(str1); //輸出:日 is a beautiful 日, 日 日 happy! </script>
8、正則應用
正則表達式也叫規則表達式,所以在編寫時,和編寫 JS 的流程一樣,先慮再寫。最重要的就是,要搞清楚他所要表達的規則,先仔細端詳其外表,看他到底長的什麼模樣,也就是以什麼樣的格式存在,再根據這種格式去寫表達式,看是否能達到我們預期的目的,如果未達到,其實一般情況下直接將格式描述成表達式,都不會達到預期的效果,好在我們的主框架已經有了,我們只需要知道是什麼地方出錯了,什麼地方沒有達到預期,就可以很簡單的在這個框架基礎上稍加修改,最後就是完美的表達式了。比如要寫一個驗證手機號的正則表達式,手機號大家都知道是 11 位,全部為數字,而且開頭是 1,緊跟著的 2 位,因為運營商不同,可有多種組合,後面 8 位是任意數字,所以我們就可以規定開頭必須為 1,後面 2 位根據各運營商提供的不同組合進行限定,最後再輸入 8 位任意數字。這樣主框架就算完成了,但是手機號也有特殊情況,比如移動給手機號碼前邊加上 +86 依然可以使用,必要的時候我們還需要把這種情況考慮進去,不然用戶輸入了自己的移動手機號給前邊加了個 +86,然後點擊提及,系統 "啪" 彈出一個窗口,你輸入的是毛線,系統不識別,這樣就鬧笑話了,所以再只需要對框架做出修改,把這種情況考慮進去,就大功告成了。
這麼說起來正則表達式貌似很簡單的樣子,其實挺難的,why are you so diao?歸根結底就是這種一般人很難看懂的表達方式,自己當時寫的時候很明白表達的是什麼,過段時間回頭,哎喲我去,怎麼不認識了。其實這是一個熟能生巧的過程,記得有篇課文中寫到“好記性不如爛筆頭”,勤能補拙,多動手多寫多思考,通過碼海戰術,反復推敲代碼,讓自己身經百戰,見的多了,自然就不虛了,編程是一門藝術,精通任何一門藝術,都需要大量的練習和領悟,知識就是一個積累的過程,當然更重要的還是要自己去總結歸納,讓知識真正屬於自己。我覺著寫程序這東西吧,最重要的還是思維,讓代碼始終跟著這種思維走,目的只有一個,怎麼簡單怎麼省事怎麼做,當然不是偷工減料,要明白需要什麼,不需要什麼,要呈現出什麼樣的效果,應該怎麼去一步步實現,只要有這種實現目的的思維,就可以讓代碼始終保持著清晰簡潔的狀態,加快編寫代碼的效率,還有助於排錯,也有利於代碼的優化。那個好像扯太遠了,每個人都有自己思考問題的方式,有不同的做事風格,只要最優化解決問題就好了,回到正事,接下來看看正則表達式應用的兩個實例。
(1)、正則驗證 QQ 號
思路分析:QQ 號有一個特性全部為數字,而且第一位不為 0,那麼就可以這樣寫 /^[1-9]/,開頭為 1-9 隨便哪個數字,常見的 QQ 號最少的是 5 位數,最多的是 10 位數,那麼可以使用量詞 {n,m} 限定位數,表達式為 /\d{5,10}/,這有一個小問題,前邊我們已經限定了開頭的第一位,那就說明還可以再輸入至少 4 位,最多 9 位的數字,這樣才匹配了最少 5 位最多 10 位,將表達式改為 /\d{4,9}/,最後再限定結尾不能是非數字,就完事了。下面看代碼是怎麼完成的:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>JavaScript實例</title> <script> window.onload = function (){ var oBtn = document.getElementById('btn1'); oBtn.onclick = function (){ var oTxt = document.getElementById('txt1').value; var re = /^[1-9]\d{4,9}$/; //用定義的正則表達式檢測輸入框的值是否匹配。 if(re.test(oTxt)){ alert("格式正確"); } else{ alert('輸入錯誤'); } }; }; </script> </head> <body> <input id="txt1" type="text" placeholder="請輸入QQ"> <input id="btn1" type="button" value="驗證"> </body> </html>
(2)、正則驗證郵箱
思路分析:先端詳下郵箱的外表,隨便來個 abc123_@ss789.xyz,郵箱是典型的粗俗的分析下其結構組成,大致可分為五部分,第一部分若干字母、若干數字還有一個下劃線,第二部分是一個 @,第三部分又是若干字母、若干數字,第四部分是一個點,最後一部分又是若干字母,诶、郵箱長的好復雜,各種若干。現在我們看光了郵箱的模樣,清楚了郵箱的規則,就可以使用表達式描述了,第一部分可寫為 /\w+/,表示若干英文,第二部分就采用 @,第三部分可表達為 [a-z0-9]+,若干字母數字都可以,第四部分需要注意,點在正則中代表任意字符,如果想直接顯示為點,就需要使用轉義,就寫為 \.,最後一部分若干英文,表達為 [a-z]+,這樣就用正則的規則把郵箱的規則描述完了,最後再使用忽略大小寫,將格式整理下:/\w+@[a-z0-9]+\.[a-z]+/ 下面就用我們分析的表達式直接驗證一下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>JavaScript實例</title> <script> window.onload=function (){ var oBtn=document.getElementById('btn1'); var oTxt=document.getElementById('txt1'); oBtn.onclick=function (){ var re=/\w+@[a-z0-9]+\.[a-z]+/i; if(re.test(oTxt.value)){ alert('合法郵箱'); } else{ alert('非法郵箱'); } }; }; </script> </head> <body> <input id="txt1" type="text" placeholder="請輸入郵箱"> <input id="btn1" type="button" value="驗證"> </body> </html>
將我們上面用於分析的郵箱例子 abc123_@ss789.xyz 拿來檢測,OK,合法郵箱,這就沒問題了嗎?我們再來驗證下這個郵箱:正則abc123_@ss789.xyz 校驗,OK,還是合法郵箱,這郵箱看著都不正規,跟我們之前分析的郵箱樣子,長的從本質上都不一樣,正則怎麼會判斷合法呢?這不是我們要的效果,顯然是我們的表達式有點小問題,就像之前說的,一般情況下直接將格式描述成表達式,都不會達到預期的效果,那怎麼解決呢?先來分析下是什麼原因導致的,其實是因為正則對象方法 test() 造成的,該方法有一個特性:只要這個字符串其中的一部分符合要求,就返回 true。解決方法其實也很簡單,讓整個字符串都被正則檢測,而不只是檢測一部分,所以再加上行首行尾就 OK 了。其實熟練了正則之後,像這樣的小問題,一般也不可能出現,這裡注重點是思路,要養成一種編寫代碼的思維模式。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>JavaScript實例</title> <script> window.onload=function (){ var oBtn=document.getElementById('btn1'); var oTxt=document.getElementById('txt1'); oBtn.onclick=function (){ var re=/^\w+@[a-z0-9]+\.[a-z]+$/i; if(re.test(oTxt.value)){ alert('合法郵箱'); } else{ alert('非法郵箱'); } }; }; </script> </head> <body> <input id="txt1" type="text" placeholder="請輸入郵箱"> <input id="btn1" type="button" value="驗證"> </body> </html>
現在對剛才的 2 個郵箱再次驗證,第一個合法,第二個非法,這個正則驗證郵箱的表達式就沒問題了。其實還是不夠嚴謹,現在網站大多要填郵箱的地方,郵箱的服務器地址也就是後綴名如 @qq.com 等都提供了下拉列表,可供用戶選擇,如果是需要整個郵箱都自行輸入,那麼這個正則表達式問題就來了,郵箱的後綴名可以分為幾類,其第三部分和最後一部分都是固定的格式,如果使用該表達式驗證,那事就大了,因為我們給每一部分定義的都是可輸入若干任意字符,很顯然這是非法的格式,郵箱的後綴是需要做限定的,這裡只是簡單的做一個實現思路的分析,在真正用的時候,還需要具體問題具體對待。像這種需要驗證的東西,前端不可能做到完美,前端就算寫的再嚴謹,也是很容易出問題的,所以這是屬於後端干的事,但是前端可以對用戶的輸入做一個簡單的格式驗證,只有確保用戶輸入正確了,再配合後端,那就是事半功倍的。