困于JavaScript的正則表達(dá)式

前言

為什么說(shuō)是困于呢?原因很簡(jiǎn)單啦,因?yàn)閖s的正則表達(dá)式語(yǔ)法是基于Perl5語(yǔ)言,但是ECMAScript只是支持里其中的一部分語(yǔ)法,不過(guò),已經(jīng)有了這部分的支持就已經(jīng)足夠js的使用了,畢竟需要前端進(jìn)行匹配的情況并不難也不多。我之前學(xué)習(xí)PHP的時(shí)候,有了解過(guò)正則,但沒(méi)仔細(xì)深入。這篇文章會(huì)講述兩個(gè)部分,一個(gè)是基于js的正則基礎(chǔ)規(guī)則(深入的,本寶寶也不明白),另一個(gè)是介紹在js中是如何使用正則匹配的。

基于js的正則基礎(chǔ)規(guī)則

  • 直接量字符

什么叫直接量字符呢?我的理解是,正則表達(dá)式中的所有字母和數(shù)字都是直接按照字面的含義進(jìn)行匹配的,這叫直接量字符,還有另外一種就是通過(guò) 反斜杠 \ 作為前綴的轉(zhuǎn)義字符,例如我們熟知的換行符\n,以下是一些可能使用到的直接量字符表

常用直接量字符表

字符 匹配內(nèi)容 注釋
字母和數(shù)字 自己本身
\t 水平制表符
\n 換行符
\v 垂直制表符
\f 換頁(yè)符
\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)容都挺常用的,如果可以的話,能把這些字符類都記下來(lái)就最好不過(guò)了,如果記不下來(lá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_]。話說(shuō),我的犀牛書應(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)想到這些問(wèn)題了。我們可以用\d{10}來(lái)完美的匹配十個(gè)數(shù)字。這就是重復(fù)字符的用法啦

常用重復(fù)字符表
ps:重復(fù)字符是作用于其前一個(gè)直接量字符或字符類的

字符 含義 例子 注釋
{n,m} n<=重復(fù)匹配次數(shù)<=m \d{1,4} 由于\d是匹配一個(gè)數(shù)字,所以總體來(lái)說(shuō)是匹配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)可以跳過(guò)。使用上表的重復(fù)字符進(jìn)行重復(fù)匹配的時(shí)候,是盡可能多的匹配。如有正則\b+和一組數(shù)字1231243,正則可以匹配該串?dāng)?shù)字里的任意一組,如1、12、123等等,這就是貪婪性的重復(fù)。但是使用\b+?作為正則的話,就會(huì)在匹配了第一個(gè)數(shù)字1之后停止匹配。在待匹配的字符后面加一個(gè)“?”,就可以開啟非貪婪匹配了,如“ *? ”。不過(guò),我們必須要在“整個(gè)表達(dá)式匹配成功”的前提下,貪婪模式才真正的影響著子表達(dá)式的匹配行為。如果整個(gè)表達(dá)式匹配失敗,貪婪模式只會(huì)影響匹配過(guò)程,對(duì)匹配結(jié)果的影響無(wú)從談起。其實(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è)+,說(shuō)明匹配前一項(xiàng)1或者是更多次,如1A2A這樣的組合也是可以被匹配的
\n 引用,通過(guò)記錄前面的括號(hào)分組數(shù)(嵌套的也算),便于在后面直接引用 (\dA(\dB))(\dC)\3 \3引用的是(\dC)組,所以能通過(guò)匹配的字符應(yīng)該是1A2B3C3C,注意引用的是(\dC)項(xiàng)的匹配結(jié)果,如1A2B3C4C是不能匹配成功的
(?:...) 只組合,不被引用記錄 (\dA(\dB))(?:\dE)(\dC)\3 \3引用的還是(\dC)組,能通過(guò)匹配的字符串,形為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”是能通過(guò)匹配的,因?yàn)樵撟址锩娴?bbbb2通過(guò)了正則規(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è)說(shuō)了,忘了的話,就向上翻看以下吧。

正則解析示意圖

雖然正則表達(dá)式看起來(lái)很長(zhǎng)很麻煩的樣子,但是將其拆分來(lái)看,還是很容易看懂的。

以上的就是基本的正則使用規(guī)則,接下來(lái)是介紹如何在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í)行匹配搜索,如果它沒(méi)有找到任何匹配,就會(huì)返回null值,如果匹配成功就會(huì)返回一個(gè)數(shù)組,該數(shù)組的index屬性包含了發(fā)生匹配的位置。通過(guò)RegExp對(duì)象的lastIndex屬性可以知道,exec( )方法的下一次匹配位置在哪里。注意:exec( )方法最好要與修飾符g一起使用,不然瀏覽器可能會(huì)被你弄崩潰的哦,切記切記。至于原因,大家可以自行查閱資料,我怕我說(shuō)不清楚的話,會(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é)果為:

exec( )的使用

這里我使用兩個(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é)果為:


test( )的使用

可以看出,如果只是想驗(yàn)證字符串時(shí)候符合正則規(guī)則的話,用test( )方法就可以了。

吐槽一下

寫的不是很好,但是在javaScript中的基本正則使用都已經(jīng)解釋清楚了。因?yàn)楹Q嘧罱恢痹诳荚嚕允菙鄶嗬m(xù)續(xù)寫的,就當(dāng)是拿來(lái)放松心情了。都考了3個(gè)星期了,明天是這星期的最后一門,加油啊親愛的,趕緊滾去復(fù)習(xí),明天考完試我就讓你看完島上書店>_<

by haiyan

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容