1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        簡單的復(fù)習(xí)一下正則表達(dá)式

        共 4975字,需瀏覽 10分鐘

         ·

        2021-08-05 21:00

        一、前言

        正則表達(dá)式,對大家來說既熟悉又陌生。熟悉是因?yàn)楣ぷ髦杏泻芏鄨鼍澳苡玫?,比如手機(jī)號、郵箱、密碼等規(guī)則校驗(yàn)。

        陌生則是因?yàn)檎齽t表達(dá)式看上去就是一堆亂碼,且一眼看上去很難看懂匹配規(guī)則。有時(shí)候在網(wǎng)上去找一個(gè)特定規(guī)則的正則表達(dá)式,搜出來的結(jié)果各不相同,執(zhí)行效果更是不盡人意,想自己去修改,感覺也無從下手。

        今天就花費(fèi)30分鐘時(shí)間,帶領(lǐng)大家從另一個(gè)角度去剖析匹配的目的,理解匹配的思路,一步一步抽絲剝繭去學(xué)會怎么寫正則表達(dá)式(讀正則表達(dá)式遠(yuǎn)比寫正則表達(dá)式要困難的多)。

        二、理解正則要干的事情

        正則要干的事情,可以總結(jié)為以下靈魂三問:

        Q1、匹配啥?
        Q2、匹配不是啥?
        Q3、匹配多少次?

        Q1、匹配啥?

        這個(gè)比較好理解,比如想匹配字符a,那就直接寫/a/,只要字符串某個(gè)位置是a就可以匹配上:

        /a/.test("javascript") //true
        復(fù)制代碼

        匹配以a開頭的字符串,就加上元字符^(開始位置標(biāo)識),/^a/

        /^a/.test("javascript") //不是以a開頭返回false
        /^a/.test("abc") //是以a開頭返回true
        復(fù)制代碼

        匹配以a結(jié)尾的字符串,就加上元字符$(結(jié)束位置標(biāo)識),/a$/

        /a$/.test("javascript") //不是以a結(jié)尾返回false
        /a$/.test("cba") //是以a結(jié)尾返回true
        復(fù)制代碼

        匹配字符a或b,可以把對應(yīng)的字符放入中括號里/[ab]/,只要字符串包含a或者b就可以匹配上:

        /[ab]/.test("byte") //true
        復(fù)制代碼

        匹配字符串a(chǎn)bc或xyz,/abc|xyz/

        /abc|xyz/.test("aabbxyz") //本字符串包含xyz,所以返回true
        復(fù)制代碼

        ① 匹配啥前面的(前瞻)

        exp1(?=exp2):匹配exp2前面的exp1,匹配結(jié)果不包含exp2

        比如要匹配字符串中script前面的部分java, /java(?=script)/

        /java(?=script)/.test("javascript,javaee,typescript") //字符串中javascript符合規(guī)則 會返回ture

        //1、用exec方法來驗(yàn)證下匹配的結(jié)果
        /java(?=script)/.exec("javascript,javaee,typescript")
        //2、得到匹配結(jié)果如下:
        ["java", index: 0, input: "javascript,javaee,typescript", groups: undefined]
        //3、會發(fā)現(xiàn)匹配到的是java,index是0,說明找到了的是javascript中script前面的java
        復(fù)制代碼

        ② 匹配啥后面的(后顧)

        (?<=exp2)exp1:匹配exp2后面的exp1,匹配結(jié)果不包含exp2

        比如要匹配字符串中java后面的部分ee, /java(?<=ee)/

        /(?<=java)ee/.test("javascript,javaee,typescript") //字符串中javaee符合規(guī)則 會返回ture

        //1、用exec方法來驗(yàn)證下匹配的結(jié)果
        /(?<=java)ee/.exec("javascript,javaee,typescript")
        //2、得到匹配結(jié)果如下:
        ["ee", index: 15, input: "javascript,javaee,typescript", groups: undefined]
        //3、會發(fā)現(xiàn)匹配到的是ee,index是15,說明找到了的是javaee中java后面的ee
        復(fù)制代碼

        Q2、匹配不是啥?

        匹配不是啥,意思就是取反,只要不是這些的都可以匹配,比如不想匹配字符a,正則寫法為/[^a]/,是在中括號里面加上元字符^,這樣只要字符串滿足有不是這個(gè)集合里面的字符,都可以被匹配上:

        /[^a]/.test("aaa") //字符串全是a,返回false
        /[^a]/.test("abc") //字符串不全是a,返回true
        復(fù)制代碼

        匹配不是以a開頭的,跟之前匹配啥類似,加上元字符^,/^[^a]/

        /^[^a]/.test("javascript") //此字符串不是以a開頭,返回true
        /^[^a]/.test("abc") //此字符串是以a開頭,返回false
        復(fù)制代碼

        匹配不是以a結(jié)束的,也跟之前匹配啥類似,加上元字符$,/[^a]$/

        /[^a]$/.test("javascript") //此字符串不是以a結(jié)束,返回true
        /[^a]$/.test("cba") //此字符串是以a結(jié)束,返回false
        復(fù)制代碼

        不匹配字符a、b、c,可以把對應(yīng)的字符都放入中括號里/[^abc]/

        /[^abc]$/.test("abccba") //此字符串的字符全部都不符合,返回false
        復(fù)制代碼

        ① 匹配后面不是啥的(負(fù)前瞻)

        exp1(?!exp2):匹配后面不是exp2的exp1,匹配結(jié)果不包含exp2

        比如要匹配字符串中后面不是script的java, /java(?!script)/

        /java(?!script)/.test("javascript,javaee,typescript") //字符串javaee符合規(guī)則 會返回ture

        //1、用exec方法來驗(yàn)證下匹配的結(jié)果
        /java(?!script)/.exec("javascript,javaee,typescript")
        //2、得到匹配結(jié)果如下:
        ["java", index: 11, input: "javascript,javaee,typescript", groups: undefined]
        //3、會發(fā)現(xiàn)匹配到的是java,index是11,說明找到了的是javaee中的java,因?yàn)檫@個(gè)java后面是ee
        復(fù)制代碼

        ② 匹配前面不是啥的(負(fù)后顧)

        (?<!exp2)exp1:匹配前面不是exp2的exp1,匹配結(jié)果不包含exp2

        比如要匹配字符串中前面不是java的script,/(?<!java)script/

        /(?<!java)script/.test("javascript,javaee,typescript") //字符串中typescript符合規(guī)則 會返回ture

        //1、用exec方法來驗(yàn)證下匹配的結(jié)果
        /(?<!java)script/.exec("javascript,javaee,typescript")
        //2、得到匹配結(jié)果如下:
        ["script", index: 22, input: "javascript,javaee,typescript", groups: undefined]
        //3、會發(fā)現(xiàn)匹配到的是script,index是22,說明找到了的是typescript中type后面的script
        復(fù)制代碼

        ③ 不匹配包含abc的字符串

        這是一個(gè)比較特殊的匹配行為,如果只是寫成/[^abc]/的話,這只意味著字符串不能全是由a、b、c這三個(gè)組成的,跟需求不匹配。

        那我們要從另外一個(gè)角度去分析,字符串的任意一個(gè)位置開始都不能連續(xù)出現(xiàn)abc,我們可以利用負(fù)前瞻的特性來匹配,然后一步一步來實(shí)現(xiàn)這個(gè)正則:

        1. 位置后面不能是abc,使用負(fù)前瞻匹配位置:/(?!abc)/

        2. 從開始到結(jié)束每個(gè)位置都要覆蓋到,添加開始結(jié)束標(biāo)記:/^(?!abc)/$

        3. 這個(gè)位置后面可以是其他的字符,用\w來表示:/^(?!abc)\w$/

        4. 滿足上面情況后的位置,可以連續(xù)出現(xiàn)多個(gè),用+來表示數(shù)量:/^((?!abc)\w)+$/

        /^((?!abc)\w)+$/.test("cbacbac") //本字符串中不包含連續(xù)的abc,結(jié)果返回true
        /^((?!abc)\w)+$/.test("cbacbabc") //本字符串中包含連續(xù)的abc,結(jié)果返回false
        復(fù)制代碼

        Q3、匹配多少次?

        匹配一次可以什么都不用定義,比如匹配一個(gè)數(shù)字/\d/,如果要匹配連續(xù)三個(gè)數(shù)字最簡單的方式就是連續(xù)寫三次:/\d\d\d/,這樣寫本身是沒有問題的,能正確匹配。

        但是如果次數(shù)太多或者次數(shù)不確定,這么寫肯定不行,所以可以加上長度規(guī)則:

        *:匹配任意次

        +:最低匹配1次

        ?:匹配1次或者0次

        {m}:匹配m次

        {m,}:最低匹配m次

        {m,n}:最低匹配m次,最多匹配n次,m需要小于等于n

        正則默認(rèn)是貪婪匹配,就是符合條件的會一直匹配,如果想阻止貪婪匹配,可以在長度規(guī)則后面加一個(gè)?,比如:

        /\d{2,}/.exec("1234567890")
        //得到匹配結(jié)果如下,會匹配到所有數(shù)字:
        ["1234567890", index: 0, input: "1234567890", groups: undefined]

        //1、添加?,阻止非貪婪匹配后
        /\d{2,}?/.exec("1234567890")
        //2、得到匹配結(jié)果如下,只會匹配2個(gè)數(shù)字:
        ["12", index: 0, input: "1234567890", groups: undefined]
        復(fù)制代碼

        ① 使用分組

        如果想匹配多次某個(gè)單詞如regregregregregreg時(shí)候怎么辦,我們看到reg連續(xù)出現(xiàn)了6次,如果傻傻的把6個(gè)reg寫在了正則表達(dá)式中肯定不合適,我們就可以利用分組來實(shí)現(xiàn),我們把reg放在括號里面,然后讓這個(gè)分組重復(fù)6次,/(reg){6}/

        /(reg){6}/.test("regregregregregreg") //匹配成功,返回true
        復(fù)制代碼

        不過這樣利用分組是有個(gè)前提,就是知道要匹配的字符串就是reg,然后重復(fù)這個(gè)分組。如果想匹配類似8899或者5522這種重疊類型的字符怎么辦呢?那我們可以把重疊的第一個(gè)放入分組,再通過\n捕獲這個(gè)分組內(nèi)容來匹配下一個(gè):

        /(\d)\1(\d)\2/.exec("2345566789")
        //得到匹配結(jié)果如下,返回了5566,分組對應(yīng)的5、6也被返回
        ["5566", "5", "6", index: 3, input: "2345566789", groups: undefined]
        復(fù)制代碼

        ② 分組捕獲

        默認(rèn)的分組是可以被捕獲的,上面的\1、\2是在正則表達(dá)式內(nèi)部捕獲的分組。如果想在外部去捕獲分組匹配的數(shù)據(jù)可以使用RegExp.$1-$9來獲取。只要正則匹配了就會有。可以使用test、exec或者str的replace方法來獲取$1-$9

        使用test:

        /([a-z]{2})(\d{2})/.test("xyz123")
        RegExp.$1 //返回第一個(gè)分組表達(dá)式匹配到的內(nèi)容 yz
        RegExp.$2 //返回第二個(gè)分組表達(dá)式匹配到的內(nèi)容 12
        復(fù)制代碼

        使用replace:

        "xyz123".replace(/([a-z]{2})(\d{2})/,'$2$1')
        //會返回結(jié)果:x12yz3,就是把第一個(gè)分組匹配到的內(nèi)容yz和第二個(gè)分組匹配到的內(nèi)容12互換了
        復(fù)制代碼

        ③ 分組不捕獲

        如果不想捕獲分組,只需要在分組內(nèi)加上?:就可以了

        /([a-z]{2})(?:\d{2})/.test("xyz123")
        RegExp.$1 //返回第一個(gè)分組表達(dá)式匹配到的內(nèi)容 yz
        RegExp.$2 //分組未被捕獲 返回空字符串
        復(fù)制代碼

        三、總結(jié)

        本文不去贅述元字符的含義以及組合使用方法,這些是需要記死背硬的東西。而是教給大家一種如何切入正則表達(dá)式的思維,怎么去一步步分析要匹配的需求,把長的、復(fù)雜的需求拆成短的、簡單的,正向不行的就逆向去分析,一點(diǎn)一點(diǎn)去組合,然后回歸靈魂三問:匹配啥?匹配不是啥?匹配多少次? ,去完成符合要求的正則表達(dá)式。

        轉(zhuǎn)自:https://juejin.cn/post/6939854031787393031


        瀏覽 130
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評論
        圖片
        表情
        推薦
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            123草逼 | 成人黄色大片 | 日韩黄色A片 | 一级片免费在线播放 | 在线播放 神尾舞视频 | 成人第一色 | 黄色小视频免费在线观看 | 性乳燕三级在线观看 | 欧美黄色一级大片 | 美女骚逼逼 |