前言
為什么說是困于呢?原因很簡(jiǎn)單啦卷要,因?yàn)閖s的正則表達(dá)式語法是基于Perl5語言辉懒,但是ECMAScript只是支持里其中的一部分語法屈糊,不過玩徊,已經(jīng)有了這部分的支持就已經(jīng)足夠js的使用了租悄,畢竟需要前端進(jìn)行匹配的情況并不難也不多。我之前學(xué)習(xí)PHP的時(shí)候恩袱,有了解過正則泣棋,但沒仔細(xì)深入。這篇文章會(huì)講述兩個(gè)部分憎蛤,一個(gè)是基于js的正則基礎(chǔ)規(guī)則(深入的外傅,本寶寶也不明白),另一個(gè)是介紹在js中是如何使用正則匹配的俩檬。
基于js的正則基礎(chǔ)規(guī)則
-
直接量字符
什么叫直接量字符呢?我的理解是碾盟,正則表達(dá)式中的所有字母和數(shù)字都是直接按照字面的含義進(jìn)行匹配的棚辽,這叫直接量字符,還有另外一種就是通過 反斜杠 \ 作為前綴的轉(zhuǎn)義字符冰肴,例如我們熟知的換行符\n屈藐,以下是一些可能使用到的直接量字符表
常用直接量字符表
字符 | 匹配內(nèi)容 | 注釋 |
---|---|---|
字母和數(shù)字 | 自己本身 | |
\t | 水平制表符 | |
\n | 換行符 | |
\v | 垂直制表符 | |
\f | 換頁符 | |
\r | 回車符 | |
\0 | NUL字符 | 也就是null |
這表格并不完整榔组,但是,其實(shí)除了第一個(gè)「字母和數(shù)字」是有用的以外联逻,其它用的很少搓扯。
在正則表達(dá)式中,許多的標(biāo)點(diǎn)符號(hào)是有特殊含義的包归,它們并不想字母和數(shù)字一樣锨推,直接進(jìn)行字面意思的匹配。例如公壤,你想要匹配一個(gè) 點(diǎn). 换可,但是如果你在正則表達(dá)式中直接寫點(diǎn)的話,會(huì)發(fā)現(xiàn)其它亂七八糟的東西也會(huì)被匹配上厦幅,這時(shí)候就要記住使用閃亮的 反斜杠 \ 了沾鳄,把它加在你要匹配的符號(hào)前面,就能消除符號(hào)對(duì)于正則表達(dá)式的特殊含義确憨,如 \ . 译荞,就可以了。
有特殊含義的符號(hào)有 ^ $ . * + ? = ! : | \ / ( ) [ ] { }
當(dāng)然休弃,如果你記不住的話磁椒,你也可以在所有你想要匹配的標(biāo)點(diǎn)符號(hào)前加上閃亮的 反斜杠 \ ,這樣就可以避免出錯(cuò)了玫芦。
-
字符類
字符類就是將直接量字符單獨(dú)放進(jìn)方括號(hào)內(nèi)浆熔,例如這樣[a,b,\t],意思是匹配a或b或水平制表符桥帆。以下是常用字符類的表格
常用字符類表
字符 | 匹配內(nèi)容 | 注釋 |
---|---|---|
[a,b] | a或者是b | 只匹配方括號(hào)里的一個(gè) |
[^a,b] | 除了a和b的其它內(nèi)容 | 其它內(nèi)容里面包含了&*^之類的亂七八糟的字符 |
. | 除了換行符和unicode終止符意外的其它字符 | |
\w | 等價(jià)于[a-zA-Z0-9_] | 注意最后還包含了一個(gè)閃亮的下劃線_ |
\W | 等價(jià)于[^a-zA-Z0-9_] | |
\d | 任何ASCII數(shù)字医增,等價(jià)與[0-9] | 你可以完美的忽略ASCII這東西 |
\D | 任何除ASCII數(shù)字以外的字符,等價(jià)于[^0-9] | |
\s | 任何unicode的空白符 | |
\S | 任何非unicode空白符的字符 | 注意老虫,\W 和\S是不一樣的 |
這個(gè)表格的內(nèi)容都挺常用的叶骨,如果可以的話,能把這些字符類都記下來就最好不過了祈匙,如果記不下來忽刽,那最簡(jiǎn)單的[a-zA-Z0-9_]、[^a-zA-Z0-9_]用法夺欲,總該要會(huì)使用吧跪帝。
注:js的犀牛書里邊\w等價(jià)于[a-zA-Z0-9],但是我查了網(wǎng)上的資料些阅,又進(jìn)行了測(cè)試伞剑,其實(shí)里面應(yīng)該包含了下劃線的,也就是應(yīng)該等價(jià)于[a-zA-Z0-9_]市埋。話說黎泣,我的犀牛書應(yīng)該是正版的啊恕刘,怎么會(huì)犯這樣的錯(cuò)誤......
-
重復(fù)字符
這種字符就是為了上面的直接量字符和字符類提供重復(fù)服務(wù)的標(biāo)記。例如抒倚,我們現(xiàn)在已經(jīng)知道了\d表示的是一個(gè)0到9中的某個(gè)數(shù)字褐着,但是,如果我們想要表示的是兩個(gè)數(shù)字呢托呕?\d\d唄含蓉,那十個(gè)呢?額......放心啦镣陕,偉大的程序員在設(shè)計(jì)的時(shí)候肯定就已經(jīng)想到這些問題了谴餐。我們可以用\d{10}來完美的匹配十個(gè)數(shù)字。這就是重復(fù)字符的用法啦
常用重復(fù)字符表
ps:重復(fù)字符是作用于其前一個(gè)直接量字符或字符類的
字符 | 含義 | 例子 | 注釋 |
---|---|---|---|
{n,m} | n<=重復(fù)匹配次數(shù)<=m | \d{1,4} | 由于\d是匹配一個(gè)數(shù)字呆抑,所以總體來說是匹配1到4個(gè)數(shù)字 |
{n,} | n<=重復(fù)匹配次數(shù) | \d{3岂嗓,} | 匹配3個(gè)以上數(shù)字 |
{n} | 重復(fù)匹配次數(shù)=n | \d{3} | 匹配3個(gè)數(shù)字 |
? | 重復(fù)匹配次數(shù)0次或1次鹊碍,等價(jià)與{0,1} | \d? | 匹配0個(gè)或這是1個(gè)數(shù)字 |
+ | 1<=重復(fù)匹配次數(shù)厌殉,等價(jià)與{1,} | \d+ | 匹配1個(gè)或或者是更多數(shù)字 |
* | 重復(fù)匹配0次或多次,等價(jià)于{0,} | \d* | 匹配0個(gè)或者是多個(gè)數(shù)字 |
還有一個(gè)概念是使用“侈咕?”進(jìn)行非貪婪性的重復(fù)公罕,如果對(duì)正則的要求不高,這個(gè)知識(shí)點(diǎn)可以跳過耀销。使用上表的重復(fù)字符進(jìn)行重復(fù)匹配的時(shí)候楼眷,是盡可能多的匹配。如有正則\b+和一組數(shù)字1231243熊尉,正則可以匹配該串?dāng)?shù)字里的任意一組罐柳,如1、12狰住、123等等张吉,這就是貪婪性的重復(fù)。但是使用\b+?作為正則的話催植,就會(huì)在匹配了第一個(gè)數(shù)字1之后停止匹配肮蛹。在待匹配的字符后面加一個(gè)“?”创南,就可以開啟非貪婪匹配了伦忠,如“ *? ”。不過扰藕,我們必須要在“整個(gè)表達(dá)式匹配成功”的前提下缓苛,貪婪模式才真正的影響著子表達(dá)式的匹配行為。如果整個(gè)表達(dá)式匹配失敗邓深,貪婪模式只會(huì)影響匹配過程未桥,對(duì)匹配結(jié)果的影響無從談起。其實(shí)里面水還很深的芥备,如果想要弄清楚具體的非貪婪性重復(fù)的使用冬耿,那還要查閱更多的資料。
-
選擇萌壳、分組和引用
都是很字面的意思亦镶,選擇就是多個(gè)正則規(guī)則里面選擇一個(gè);分組就是將多個(gè)小正則規(guī)則作為一個(gè)小組袱瓮;引用就是引用前面的某一項(xiàng)正則規(guī)則的匹配結(jié)果缤骨。還是上圖表吧
字符 | 含義 | 例子 | 注釋 |
---|---|---|---|
| | 選擇,可能用于匹配的正則規(guī)則是該豎線左邊的或右邊的 | \d|A | 匹配一個(gè)數(shù)字或一個(gè)大寫字母A尺借,因?yàn)槭菑腬d和A兩個(gè)規(guī)則中選一個(gè)進(jìn)行匹配绊起,所以不能匹配類似于1A這樣的數(shù)字組合 |
(...) | 組合,把多項(xiàng)正則規(guī)則組合在一起燎斩,便于重復(fù)字符等對(duì)它們的共同作用 | (\dA)+ | \dA匹配的是1A這樣的“一個(gè)數(shù)字一個(gè)字母A”的組合虱歪,但是后面跟了一個(gè)+,說明匹配前一項(xiàng)1或者是更多次栅表,如1A2A這樣的組合也是可以被匹配的 |
\n | 引用笋鄙,通過記錄前面的括號(hào)分組數(shù)(嵌套的也算),便于在后面直接引用 | (\dA(\dB))(\dC)\3 | \3引用的是(\dC)組怪瓶,所以能通過匹配的字符應(yīng)該是1A2B3C3C萧落,注意引用的是(\dC)項(xiàng)的匹配結(jié)果,如1A2B3C4C是不能匹配成功的 |
(?:...) | 只組合洗贰,不被引用記錄 | (\dA(\dB))(?:\dE)(\dC)\3 | \3引用的還是(\dC)組找岖,能通過匹配的字符串,形為1A2B3E4C4C |
我覺得表中已經(jīng)夠詳細(xì)了哆姻,不補(bǔ)充了宣增,任性
-
匹配位置
正則表達(dá)式可以讓你選擇匹配的是一段字符串的某些位置,如定位開頭用^矛缨、定位末尾用$等爹脾。我們將這類字符稱為錨字符。
錨字符表
字符 | 含義 | 例子 | 注釋 |
---|---|---|---|
^ | 匹配字符串的開頭 | ^\d | 匹配以數(shù)字開頭的字符串箕昭,例如1abcd是能夠被匹配成功的灵妨,而abcd就不能 |
$ | 匹配字符串的末尾 | \d$ | 匹配數(shù)字結(jié)尾的字符串,如abcd1 |
\b | 匹配單詞的邊界落竹,就是位于字符\w與\w之間的位置 | \b1(\w)+2\b | 匹配的是以1開頭以2結(jié)尾的單詞泌霍,例如字符串“1111 aaa 1bbbb2 2222”是能通過匹配的,因?yàn)樵撟址锩娴?bbbb2通過了正則規(guī)則 |
還有零寬正向先行斷言(?=p)和零寬負(fù)向先行斷言(?!p)述召,不是很常用朱转,我就不解釋了蟹地,想要了解的可以自己查閱資料。
-
修飾符
這里要補(bǔ)充一個(gè)知識(shí)點(diǎn)藤为,前面所講到的正則規(guī)則都是需要放在/ /之間怪与,至于原因,后面在JS的使用舉例中會(huì)解釋缅疟。但是本小節(jié)所講的修飾符是放在/ /右邊的分别,作用是為了給前面的全體正則規(guī)則作補(bǔ)充。
修飾符
字符 | 含義 | 例子 | 注釋 |
---|---|---|---|
i | 執(zhí)行不區(qū)分大小寫的比較 | /a/i | 雖然前面定義了要匹配小寫的字母a存淫,但是由于后面的i的作用耘斩,A也是能夠匹配成功的 |
g | 執(zhí)行全局匹配,即找出一個(gè)字符串中所有的匹配項(xiàng) | /a/g | 如可以匹配字符串"acdcdacdc"中的兩個(gè)a都是會(huì)被匹配的 |
m | 多行匹配 | /^a/m | 如果有一個(gè)字符串里面有很多行桅咆,它可以匹配每一行前面的a括授,例如"abc\nbdc",會(huì)對(duì)兩行的開頭進(jìn)行匹配轧邪,但是匹配成功一個(gè)就好了 |
上面三個(gè)修飾符可以根據(jù)自己想要的效果進(jìn)行組合使用刽脖。
-
綜合舉例
在這里我會(huì)舉一個(gè)前端表單中常用的例子,那就是郵箱地址的正則驗(yàn)證忌愚。這個(gè)栗子不是很大曲管,但是味道應(yīng)該也還不錯(cuò)的吧...
上代碼:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>RegExpDemo</title>
</head>
<body>
<input type="text" id="email" placeholder="請(qǐng)您輸入郵箱地址">
<input type="submit" id="check" value="驗(yàn)證">
</body>
<script>
var email = document.getElementById("email").value;
var oCheck = document.getElementById("check");
var reg = /^\w+((-\w+)|(\.\w+))*@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/;
oCheck.onclick=function( ){
if(email != ""){
if(reg.test(email)){
alert("郵箱合法!");
}else{
alert("郵箱不合法硕糊!");
}
}
}
</script>
</html>
這個(gè)例子的驗(yàn)證結(jié)果不方便截圖院水,所以想看運(yùn)行結(jié)果的朋友,只能自己copy代碼運(yùn)行一下咯
這代碼驗(yàn)證的只是郵箱的基本形式简十,并不能驗(yàn)證郵箱地址是否真實(shí)存在檬某。有的人在做匹配的時(shí)候,@符號(hào)后面的網(wǎng)址用的是固定網(wǎng)址組合螟蝙,如(sina.cn|qq.com)之類的恢恼,但是我覺得這樣具有局限性,我們并不能完全將所有的郵箱都舉例齊全胰默,例如我學(xué)校的郵件系統(tǒng)用的就是@hfut.edu.cn场斑。要是不在組合的選擇范圍內(nèi),那我的郵箱不就不能在該網(wǎng)站上正常使用了么牵署?這不科學(xué)啊
現(xiàn)在我就用圖漏隐,開始一步一步的解析這個(gè)郵箱地址的正則,當(dāng)然奴迅,實(shí)在是很簡(jiǎn)單的青责,例如,“重復(fù)字符*表示至少匹配0次”這樣的簡(jiǎn)單概念,我就不一個(gè)一個(gè)說了脖隶,忘了的話扁耐,就向上翻看以下吧。
雖然正則表達(dá)式看起來很長(zhǎng)很麻煩的樣子浩村,但是將其拆分來看做葵,還是很容易看懂的占哟。
以上的就是基本的正則使用規(guī)則心墅,接下來是介紹如何在js中使用正則
JavaScript中的正則使用
-
RegExp對(duì)象
JavaScript中的正則表達(dá)式用RegExp對(duì)象表示,可以用RegExp( )構(gòu)造函數(shù)創(chuàng)建對(duì)象榨乎,或者是特殊的直接量//直接創(chuàng)建怎燥,如
1 var reg1= new RegExp ("\\d", "g");// 用構(gòu)造函數(shù)創(chuàng)建
2 var reg2 = /\d/g;//用直接量創(chuàng)建
注:用構(gòu)造函數(shù)創(chuàng)建RegExp對(duì)象的時(shí)候,其構(gòu)造函數(shù)可以接受兩個(gè)參數(shù)蜜暑,參數(shù)1是正則規(guī)則/ /之間的部分铐姚,參數(shù)2是正則的修飾符。而且不論是字符串直接量還是正則表達(dá)式肛捍,都要使用“\”作為轉(zhuǎn)義字符的前綴隐绵。
可以看出第二種方法比較比較方便,所以后續(xù)的例子我都會(huì)使用方法2創(chuàng)建RegExp對(duì)象拙毫。
-
RegExp對(duì)象的方法
RegExp對(duì)象定義了兩個(gè)用于執(zhí)行模式匹配操作的方法依许,分別為exec( )和test( )。
1.exec( )方法的使用
使用該方法在一個(gè)字符串中執(zhí)行匹配搜索缀蹄,如果它沒有找到任何匹配峭跳,就會(huì)返回null
值,如果匹配成功就會(huì)返回一個(gè)數(shù)組缺前,該數(shù)組的index屬性包含了發(fā)生匹配的位置蛀醉。通過RegExp對(duì)象的lastIndex屬性可以知道,exec( )方法的下一次匹配位置在哪里衅码。注意:exec( )方法最好要與修飾符g一起使用拯刁,不然瀏覽器可能會(huì)被你弄崩潰的哦,切記切記逝段。至于原因垛玻,大家可以自行查閱資料,我怕我說不清楚的話惹恃,會(huì)誤導(dǎo)大家夭谤。下面舉一個(gè)小小的栗子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>RegExpDemo1</title>
</head>
<body>
</body>
<script>
var reg = /\da/gi; //用直接量創(chuàng)建一個(gè)RegExp對(duì)象,并用于匹配一個(gè)數(shù)字和一個(gè)字母a
var text = "1a2A3b4c";
var result = null;
document.write("待匹配字符串是"+text+"<br/>");
while((result = reg.exec(text)) != null){
document.write("匹配到"+result[0]+",位置是"+result.index+",下一次開始匹配的位置是"+reg.lastIndex+";<br/>");
}
</script>
</html>
運(yùn)行結(jié)果為:
這里我使用兩個(gè)修飾符g和i巫糙,i可以讓我們既能匹配a又能匹配A朗儒。
2.test( )方法的使用
這方法與exec( )方法類似,但是比它簡(jiǎn)單。test( )方法會(huì)對(duì)字符串進(jìn)行匹配醉锄,只要匹配成功了乏悄,就返回true,反之恳不,返回false檩小。又上一個(gè)小栗子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>RegExpDemo2</title>
</head>
<body>
</body>
<script>
var reg = /\da/gi;
var text1 = "1a2A3b4c";
var text2 = "11111";
document.write("待匹配字符串是"+text1+"和"+text2+"<br/>");
document.write(reg.test(text1)+"</br>");
document.write(reg.test(text2));
</script>
</html>
運(yùn)行結(jié)果為:
可以看出,如果只是想驗(yàn)證字符串時(shí)候符合正則規(guī)則的話烟勋,用test( )方法就可以了规求。
吐槽一下
寫的不是很好,但是在javaScript中的基本正則使用都已經(jīng)解釋清楚了卵惦。因?yàn)楹Q嘧罱恢痹诳荚囎柚祝允菙鄶嗬m(xù)續(xù)寫的,就當(dāng)是拿來放松心情了沮尿。都考了3個(gè)星期了丛塌,明天是這星期的最后一門,加油啊親愛的畜疾,趕緊滾去復(fù)習(xí)赴邻,明天考完試我就讓你看完島上書店>_<
by haiyan