常用正則表達(dá)式分析(入門)

寫在開頭

在編碼過程中,正則表達(dá)式一直是經(jīng)常會(huì)出現(xiàn)但又困擾我們的知識(shí)點(diǎn),筆者就是每次遇到正則表達(dá)式就相當(dāng)頭痛,往往都是從網(wǎng)上復(fù)制一個(gè)表達(dá)式到代碼里草草了事。但其實(shí)如果不真正理解正則表達(dá)式的含義,我們就無法對(duì)其進(jìn)行修改來應(yīng)對(duì)特殊的需求。所以本文選取幾個(gè)常用的正則表達(dá)式進(jìn)行分析,旨在覆蓋基礎(chǔ)的正則表達(dá)式知識(shí),讓和我一樣的新手們不再懼怕那些看起來復(fù)雜的正則表達(dá)式。

定義

正則表達(dá)式是用于匹配字符串中字符組合的模式。

分析模式

首先我會(huì)把常用的正則表達(dá)式列出來,接著介紹與該表達(dá)式有關(guān)的知識(shí)點(diǎn),然后結(jié)合知識(shí)點(diǎn)并借用例子來逐步分析該正則表達(dá)式。最后我會(huì)列出一些匹配該正則表達(dá)式的例子。為了保證閱讀質(zhì)量,知識(shí)點(diǎn)分析不會(huì)一直重復(fù),到后來會(huì)只介紹重要或新出現(xiàn)的知識(shí)點(diǎn)。

相關(guān)連接

正式開始

用戶名:

    ^[a-z0-9_-]{3,16}$
  • 知識(shí)點(diǎn):
    • ^ :匹配輸入的開始
    • $ :匹配輸入的結(jié)束
    • {n,m} :n和m都是正整數(shù)。匹配前面的字符至少n次,最多m次。如果n或者m的值為0,這個(gè)值被忽略。
    • [a-z] :表示范圍a-z的一個(gè)字符集合,可以與該區(qū)間內(nèi)任何字符匹配。
  • 從左到右逐步分析:
    1. 字符 ^ 開始匹配輸入
    2. [a-zA-Z0-9_-]表示該字符可以與a-z,A-Z,0-9,下劃線,破折號(hào)范圍內(nèi)的任意一個(gè)字符匹配
    3. {3,16}表示用戶名里有最少3個(gè)或者最多16個(gè)上述字符
  • 匹配舉例:
    • abcde
  • 不匹配舉例:
    • ab (太短)

手機(jī)號(hào):

/^1[3|4|5|7|8][0-9]{9}$/
    //手機(jī)號(hào)的正則表達(dá)式通常被分為移動(dòng),聯(lián)通等幾種,因?yàn)楸疚淖⒅赜趯?duì)正則表達(dá)式的理解,所以不作分類,只對(duì)一個(gè)通用的表達(dá)式進(jìn)行分析。手機(jī)號(hào)的范圍以百度百科為準(zhǔn),即第一位是1開頭,第二位有3,4,5,7,8,第三位及之后的數(shù)字都是0-9的范圍
  • 知識(shí)點(diǎn):
    • ^ :匹配輸入的開始
    • $ :匹配輸入的結(jié)束
    • [a|b] :表示匹配a或者b的一個(gè)字符集合
    • [0-9] :表示范圍0-9的一個(gè)字符集合,可以與該區(qū)間內(nèi)任何字符匹配
    • {n} :n是一個(gè)正整數(shù),匹配了前面一個(gè)字符剛好發(fā)生了n次
  • 從左到右逐步分析:
    • 字符^開始匹配輸入
    • 1規(guī)定了必須第一位是1
    • [3|4|5|7|8]表示第二位可以從3,4,5,7,8這幾個(gè)數(shù)字中任選其一
    • [0-9]{9}表示匹配任意9個(gè)在0-9范圍內(nèi)的數(shù)字,同時(shí)也規(guī)定了必須有9個(gè)數(shù)
  • 匹配舉例:
    • 13456789456
  • 不匹配舉例
    • 12345678987 (第二位不屬于3,4,5,7,8任何一個(gè))
    • 138078787 (第三位開始少于9個(gè)數(shù))

郵箱:

    /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/
  • 知識(shí)點(diǎn):

    • ^ :匹配輸入的開始
    • $ :匹配輸入的結(jié)束
    • + :匹配前面一個(gè)表達(dá)式一次或多次
    • \ :將其后的特殊字符,轉(zhuǎn)義為字面量
    • [a-z] :表示范圍a-z的一個(gè)字符集合,可以與該區(qū)間內(nèi)任何字符匹配。
  • 從左到右逐步分析(舉例:wys123@gmail.com):

    1. 字符^開始匹配輸入
    2. [a-zA-Z0-9_-]表示該字符可以與a-z,A-Z,0-9,下劃線,破折號(hào)范圍內(nèi)的任意一個(gè)字符匹配,緊跟著的加號(hào)表示可以匹配多個(gè)上述范圍內(nèi)的字符 (第2步代表wys123這個(gè)部分)
    3. @規(guī)定了必須有@符號(hào)
    4. [a-zA-Z0-9_-]+ 的含義與第2步介紹的一樣 (代表gmail部分)
    5. \..從特殊字符轉(zhuǎn)義為字面量,規(guī)定了必須有. (gmail.com中的".")
    6. [a-zA-Z0-9_-]+ 的含義還是與第2步中的一樣 (代表com部分)
  • 匹配舉例:

    • mario_a@qq.com
    • mario-a@qq.com
    • mario@a-b.c
  • 不匹配舉例:

    • marioqq.com
    • mario@qqcom
    • mar&io@qq.com

十六進(jìn)制數(shù)字:

    ^#?([a-f0-9]{6}|[a-f0-9]{3})$
  • 知識(shí)點(diǎn):

    • ?:匹配前面一個(gè)表達(dá)式0次或者1次
    • (x): 匹配x并記住該匹配項(xiàng),括號(hào)被稱為捕獲括號(hào)
    • {n} :n是一個(gè)正整數(shù),匹配了前面一個(gè)字符剛好發(fā)生了n次
    • a|b :匹配a或者b
  • 從左到右逐步分析:

    1. 因?yàn)?code>?的存在,所以#在這里是可有可無的
    2. ([a-f0-9]{6}|[a-f0-9]{3})可以看成(A|B),其中A=[a-f0-9]{6},代表一個(gè)剛好存在6個(gè)范圍在af或者09的字符的集合;B=[a-f0-9]{3},代表一個(gè)剛好存在3個(gè)范圍在a-f或者0-9的集合。那么通俗講,不考慮#,被匹配的字符集合長(zhǎng)度為3或者6,這3個(gè)或者6個(gè)字符必須都在范圍a-f或0-9內(nèi)。
  • 匹配舉例:

    • #000000
    • #ffffff
    • aff
  • 不匹配舉例:

    • #00 (位數(shù)錯(cuò)誤,#后面不是3位或者6位)
    • #-aaaaa(范圍錯(cuò)誤,-不在范圍a-f或0-9內(nèi))

國(guó)內(nèi)電話號(hào)碼(帶區(qū)號(hào)):

    ^\d{3}-\d{8}|\d{4}-\d{7,8}$
  • 知識(shí)點(diǎn):

    • \d:匹配一個(gè)數(shù)字
    • {n} :n是一個(gè)正整數(shù),匹配了前面一個(gè)字符剛好發(fā)生了n次
    • {n,m} :n和m都是正整數(shù)。匹配前面的字符至少n次,最多m次。如果n活著m的值為0,這個(gè)值被忽略。
  • 分析:
    這個(gè)例子與16進(jìn)制的例子很像,可以將其看成X|Y,其中X=\d{3}-\d{8},代表3個(gè)數(shù)字+一個(gè)-+8個(gè)數(shù)字;Y=\d{4}-\d{7,8},代表4個(gè)數(shù)字+一個(gè)-+7或8個(gè)數(shù)字,所以該正則表達(dá)式匹配了兩種電話號(hào)碼的模式

  • 匹配舉例:

    • 021-86279200
    • 0574- 86279200
  • 不匹配舉例:

    • 021-86278 (不匹配,位數(shù)不夠)
    • 86279200 (不匹配,雖然有時(shí)候也會(huì)需要匹配這一類不帶區(qū)號(hào)的電話號(hào)碼,但在本文采用的表達(dá)式中強(qiáng)制要求加上區(qū)號(hào),所以這個(gè)例子也不匹配)

URL:

    ^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$
  • 知識(shí)點(diǎn):

    • \ :可以將其后的特殊字符,轉(zhuǎn)義為字面量
    • ?: 匹配前一個(gè)表達(dá)式0次或1次
    • \w :匹配一個(gè)單字字符(字母、數(shù)字或下劃線),等價(jià)于[A-Za-z0-9_]
    • * : 匹配前一個(gè)表達(dá)式0次或多次
  • 分析:
    這個(gè)表達(dá)式相對(duì)前面幾個(gè)較復(fù)雜,我們先把它分塊來看:


    URL分析
    • 紅色部分:s后面的問號(hào)代表可以匹配http或者h(yuǎn)ttps,\/轉(zhuǎn)義成了字面量,所以連在一起就是http://或者https:// ,然后紅色部分最后的問號(hào)代表https://或者http://可以都不要,直接寫url比如www.baidu.com,這也是可以被匹配的
    • 橙色部分: [\da-z\.-]代表了表示了范圍為數(shù)字,小寫字母,點(diǎn)或者-的字符集合,后面的加號(hào)表示可以匹配多個(gè)上述范圍內(nèi)的字符
    • 綠色部分: \.轉(zhuǎn)義成了字面量,這里表示必須要有一個(gè).字符
    • 藍(lán)色部分: [a-z\.]代表了范圍為小寫字母或者點(diǎn)的字符集合,{2,6}表示可以有最少2個(gè),最多6個(gè)上述范圍的字符。橙色,綠色和藍(lán)色部分組成了域名
    • 粉色部分: [\/\w\.-]表示了范圍為/,字母,數(shù)字,下劃線,點(diǎn)或者"-"的字符集合,后面的*表示可以匹配這個(gè)式子0次或者多次。其實(shí)筆者在這里對(duì)為什么要有兩個(gè)*字符表示疑問,我認(rèn)為這兩個(gè)*號(hào)作用相同,取其一即可,粉色部分是路徑和文件名
    • 綠色部分: \/轉(zhuǎn)義成字面量后,跟隨的?代表該/可有可無,換句話說,www.baidu.com/somethingwww.baidu.com/something/ 都可以被匹配。
  • 匹配舉例:

    • https://www.google.co.uk/
    • https://zh.wikipedia.org/wiki/
  • 不匹配舉例:

    • htts://www.baidu.com (http要么不存在要么整個(gè)存在,這里不符合)

匹配首尾空白字符(可用來刪除首尾空白字符)

    ^\s*|\s*$
  • 知識(shí)點(diǎn):
    • \s :匹配一個(gè)空白字符,包括空格、制表符、換頁(yè)符合換行符
    • ^ :匹配輸入的開始
    • $ :匹配輸入的結(jié)束
    • 注意 \s\S是相反的意思,不要混淆大小寫
  • 分析:
    • 其實(shí)往往越簡(jiǎn)單的表達(dá)式越難理解,對(duì)于這個(gè)表達(dá)式我決定用多個(gè)例子一步步解析。首先我們先詳細(xì)測(cè)試一下表達(dá)式^a|b$所能匹配的字符串,在字符串"aabb"中,其匹配了第一個(gè)a和第二個(gè)b,換句話說,匹配了首尾的a和b。再來看一看^a*|b*,這次用字符串aacaabbcbb來測(cè)試,可以看到匹配了首尾的"aa"和"bb",但并沒有匹配兩個(gè)c之間的aabb,這是因?yàn)?code>^和$存在的緣故,實(shí)際上它會(huì)匹配開始后和結(jié)束前的a*b*字符串. 那么現(xiàn)在我們重新來看上述的表達(dá)式,將ab都替換為\s*后,該式子匹配的是字符串首尾的連續(xù)空白字符,這里有兩個(gè)關(guān)鍵詞:首尾連續(xù)。之所以只匹配首尾,是因?yàn)樽址涫资瞧ヅ溟_始后最先被判斷的,而字符串句尾是匹配結(jié)束前最后被判斷的,所以符合了符號(hào)^$所代表的意思,至于連續(xù),則是由*所決定的,如果不帶*,那么只會(huì)匹配首尾的一個(gè)空白字符。
  • 匹配舉例:
    • aacaab bcbb(只匹配首尾空格,中間的空格不匹配)
  • 不匹配舉例:
    • a b c(只匹配首尾空格,中間的空格不匹配)

未涉及到的常用特殊字符(摘自MDN)

  • (?:x):匹配 'x' 但是不記住匹配項(xiàng)。這種叫作非捕獲括號(hào),使得你能夠定義為與正則表達(dá)式運(yùn)算符一起使用的子表達(dá)式。來看示例表達(dá)式 /(?:foo){1,2}/。如果表達(dá)式是 /foo{1,2}/,{1,2}將只對(duì) ‘foo’ 的最后一個(gè)字符 ’o‘ 生效。如果使用非捕獲括號(hào),則{1,2}會(huì)匹配整個(gè) ‘foo’ 單詞。
  • x(?=y):匹配'x'僅僅當(dāng)'x'后面跟著'y'.這種叫做正向肯定查找。
    例如,/Jack(?=Sprat)/會(huì)匹配到'Jack'僅僅當(dāng)它后面跟著'Sprat'。/Jack(?=Sprat|Frost)/匹配‘Jack’僅僅當(dāng)它后面跟著'Sprat'或者是‘Frost’。但是‘Sprat’和‘Frost’都不是匹配結(jié)果的一部分。
  • [^xyz]:一個(gè)反向字符集。也就是說, 它匹配任何沒有包含在方括號(hào)中的字符。你可以使用破折號(hào)(-)來指定一個(gè)字符范圍。任何普通字符在這里都是起作用的。例如,[^abc] 和 [^a-c] 是一樣的。他們匹配"brisket"中得‘r’,也匹配“chop”中的‘h’。

總結(jié)

至此,借用一些常見的正則表達(dá)式,已經(jīng)把MDN里提到的大部分特殊字符都分析了一遍,筆者本人也是一個(gè)新手,雖然花了很多功夫試圖透徹理解上述各個(gè)表達(dá)式的含義,但文章中肯定還存在理解有偏差的地方,歡迎指正。

最后編輯于
?著作權(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ù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,882評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,208評(píng)論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 175,746評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,666評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,477評(píng)論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,960評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,047評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,200評(píng)論 0 288
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,726評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,617評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,807評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,327評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,049評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,425評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,674評(píng)論 1 281
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,432評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,769評(píng)論 2 372

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