<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          正則表達(dá)式理論篇

          共 5767字,需瀏覽 12分鐘

           ·

          2021-09-23 17:41


          學(xué)習(xí)正則表達(dá)式的你們,有沒有發(fā)現(xiàn),一開始總是記不住語法。嗯,加深大家的印象的同時,我也是來找同道中人的。

          首先你要記住它的名字

          正則表達(dá)式
          regular expression
          縮寫 regexp 、regex 、egrep。

          正則表達(dá)式可以干嘛

          • 數(shù)據(jù)驗(yàn)證。

          • 復(fù)雜的字符串搜尋、替換。

          • 基于模式匹配從字符串中提取子字符串。

          概述

          正則表達(dá)式包括普通字符(例如,a 到 z 之間的字母)和特殊字符(稱為“元字符”)。

          若要匹配這些特殊字符,必須首先轉(zhuǎn)義字符,即,在字符前面加反斜杠字符 \**。 
          例如,若要搜索 “+”文本字符,可使用表達(dá)式 \+。
          但是大多數(shù) 特殊字符 在中括號表達(dá)式內(nèi)出現(xiàn)時失去本來的意義,并恢復(fù)為普通字符。

          構(gòu)造函數(shù)(四種寫法)

          var regex = new RegExp('xyz', 'i');  
          var regex = new RegExp(/xyz/i);
          var regex = /xyz/i;

          // ES6的寫法。ES5在第一個參數(shù)是正則時,不允許此時使用第二個參數(shù),會報(bào)錯。
          // 返回的正則表達(dá)式會忽略原有的正則表達(dá)式的修飾符,只使用新指定的修飾符。
          // 下面代碼返回”i”。
          new RegExp(/abc/ig, 'i').flags

          用于模式匹配的String方法

          • String.search()
            參數(shù):要搜索的子字符串,或者一個正則表達(dá)式。
            返回:第一個與參數(shù)匹配的子串的起始位置,如果找不到,返回-1
            說明:不支持全局搜索,如果參數(shù)是字符串,會先通過RegExp構(gòu)造函數(shù)轉(zhuǎn)換成正則表達(dá)式。

          • String.replace() 
            作用:查找并替換字符串。

            第一個參數(shù):字符串或正則表達(dá)式,
            第二個參數(shù):要進(jìn)行替換的字符串,也可以是函數(shù)。
            用法:

          替換文本中的$字符有特殊含義:

          $1、$2、...、$99 與 regexp 中的第 1 到第 99 個子表達(dá)式相匹配的文本。
          $&  與 regexp 相匹配的子串。
          $`  位于匹配子串左側(cè)的文本。
          $'  位于匹配子串右側(cè)的文本。
          $$  普通字符$。

          如:

          'abc'.replace(/b/g, "{$$$`$&$'}")
          // 結(jié)果為 "a{$abc}c",即把b換成了{(lán)$abc}
          • String.match() 參數(shù):要搜索的子字符串,或者一個正則表達(dá)式。返回:一個由匹配結(jié)果組成的數(shù)組。

          非全局檢索:如果沒有找到任何匹配的文本返回null;否則數(shù)組的第一個元素是匹配的字符串,剩下的是小括號中的子表達(dá)式,即a[n]中存放的是$n的內(nèi)容。非全局檢索返回三個屬性:length 屬性;index 屬性聲明的是匹配文本的第一個字符的位置;input 屬性則存放的是被檢索的字符串 string。

          全局檢索:設(shè)置標(biāo)志g則返回所有匹配子字符串,即不提供與子表達(dá)式相關(guān)的信息。沒有 index 屬性或 input 屬性。

          • String.split() 作用:把一個字符串分割成字符串?dāng)?shù)組。
            參數(shù):正則表達(dá)式或字符串。返回:子串組成的數(shù)組。

          RegExp的方法

          • RegExpObject.exec() 參數(shù):字符串。返回:

          非全局檢索:與String.macth()非全局檢索相同,返回一個數(shù)組或null。

          全局檢索:盡管是全局匹配的正則表達(dá)式,但是exec方法只對指定的字符串進(jìn)行一次匹配。但是可以反復(fù)調(diào)用來實(shí)現(xiàn)全局檢索。在 RegExpObject 的lastIndex 屬性指定的字符處開始檢索字符串;匹配后,將更新lastIndex為匹配文本的最后一個字符的下一個位置;再也找不到匹配的文本時,將返回null,并把 lastIndex 屬性重置為 0。

          如:

          • RegExpObject.test()

            參數(shù):字符串。
            返回:true或false。

          • RegExpObject.toString()

            返回:字符串

          字符

          | 指示在兩個或多個項(xiàng)之間進(jìn)行選擇。類似js中的或,又稱分支條件。
          / 正則表達(dá)式模式的開始或結(jié)尾。
          \ 反斜杠字符,用來轉(zhuǎn)義。
          - 連字符 當(dāng)且僅當(dāng)在字符組[]的內(nèi)部表示一個范圍,比如[A-Z]就是表示范圍從A到Z;如果需要在字符組里面表示普通字符-,放在字符組的開頭即可。

          . 匹配除換行符 \n 之外的任何單個字符。
          \d 等價[0-9],匹配0到9字符。
          \D 等價[^0-9],與\d相反。
          \w 與以下任意字符匹配:A-Z、a-z、0-9 和下劃線,等價于 [A-Za-z0-9_]。
          \W 與\w相反,即 [^A-Za-z0-9_]

          限定符(量詞字符)

          顯示限定符位于大括號 {} 中,并包含指示出現(xiàn)次數(shù)上下限的數(shù)值;*+? 這三個字符屬于單字符限定符

          {n} 正好匹配 n 次。
          {n,} 至少匹配 n 次。
          {n,m} 匹配至少 n 次,至多 m 次。
          * 等價{0,}
          + 等價{1,}
          ? 等價{0,1}

          注意:

          • 顯示限定符中,逗號和數(shù)字之間不能有空格,否則返回null!

          • 貪婪量詞*+:javascript默認(rèn)是貪婪匹配,也就是說匹配重復(fù)字符是盡可能多地匹配。

          • 惰性(最少重復(fù)匹配)量詞?:當(dāng)進(jìn)行非貪婪匹配,只需要在待匹配的字符后面跟隨一個?即可。

          var reg = /a+/;
          var reg2 = /a+?/;
          var str = 'aaab';

          str.match(reg); // ["aaa"]
          str.match(reg2); // ["a"]

          定位點(diǎn)(錨字符、邊界)

          ^ 匹配開始的位置。將 ^ 用作括號[]表達(dá)式中的第一個字符,則會對字符集求反。
          $ 匹配結(jié)尾的位置。
          \b 與一個字邊界匹配,如er\b 與“never”中的“er”匹配,但與“verb”中的“er”不匹配。
          \B 非邊界字匹配。

          標(biāo)記

          • 中括號[] 字符組;標(biāo)記括號表達(dá)式的開始和結(jié)尾,起到的作用是匹配這個或者匹配那個。
            [...] 匹配方括號內(nèi)任意字符。很多字符在[]都會失去本來的意義:[^...]匹配不在方括號內(nèi)的任意字符;[?.]匹配普通的問號和點(diǎn)號。
            但是不要濫用字符組這個失去意義的特性,比如不要使用[.]來代替\:轉(zhuǎn)義點(diǎn)號,因?yàn)樾枰冻鎏幚碜址M的代價。

          • 大括號{} 標(biāo)記限定符表達(dá)式的開始和結(jié)尾。

          • 小括號() 標(biāo)記子表達(dá)式的開始和結(jié)尾,主要作用是分組,對內(nèi)容進(jìn)行區(qū)分。

          (模式) 可以記住和這個模式匹配的匹配項(xiàng)(捕獲分組)。不要濫用括號,如果不需要保存子表達(dá)式,可使用非捕獲型括號(?:)來進(jìn)行性能優(yōu)化。
          (?:模式) 與模式 匹配,但不保存匹配項(xiàng)(非捕獲分組)。
          (?=模式) 零寬正向先行斷言,要求匹配與模式 匹配的搜索字符串。找到一個匹配項(xiàng)后,將在匹配文本之前開始搜索下一個匹配項(xiàng);但不會保存匹配項(xiàng)。
          (?!模式) 零寬負(fù)向先行斷言,要求匹配與模式 不匹配的搜索字符串。找到一個匹配項(xiàng)后,將在匹配文本之前開始搜索下一個匹配項(xiàng);但不會保存匹配項(xiàng)。

          有點(diǎn)暈?
          好,換個說法。。。

          先行斷言(?=模式):x只有在y前面才匹配,必須寫成/x(?=y)/。解釋:找一個x,那個x的后面有y。
          先行否定斷言(?!模式):x只有不在y前面才匹配,必須寫成/x(?!y)/。解釋:找一個x,那個x的后面沒有y。

          穩(wěn)住,又來了兩個斷言,來自ES7提案:

          后行斷言(?<=模式):與"先行斷言”相反, x只有在y后面才匹配,必須寫成/(?<=y)x/。解釋:找一個x,那個x的前面要有y。
          后行否定斷言(?<!模式):與”先行否定斷言“相反,x只有不在y后面才匹配,必須寫成/(?<!y)x/。解釋:找一個x,那個x的前面沒有y。

          可以看出,后行斷言先匹配/(?<=y)x/的x,然后再回到左邊,匹配y的部分,即先右后左"的執(zhí)行順序。

          零寬負(fù)向先行斷言的例子:

          var str=`<div class="o2">
                     <div class="o2_team">
                         <img src="img/logo.jpg" />
                     </div>
                 </div>`;
          // <(?!img) 表示找一個左尖括號<,而且左尖括號<的后面沒有img字符;
          // (?:.|\r|\n)*? 表示匹配左右尖括號<>里面的.或\r或\n,而且匹配次數(shù)為*?;(?:)不保存匹配項(xiàng),提高性能;
          // *后面加個? 表示非貪婪匹配。
          var reg = /<(?!img)(?:.|\r|\n)*?>/gi;
          str.match(reg);
          // 返回結(jié)果 ["<div class="o2">", "<div class="o2_team">", "</div>", "</div>"]
          • 反向引用:主要作用是給分組加上標(biāo)識符\n。 \n 表示引用字符,與第n個子表達(dá)式第一次匹配的字符相匹配。

          反向引用的例子,給MikeMike字符后加個單引號:

          var reg = /(Mike)(\1)(s)/;
          var str = "MikeMikes";
          console.log(str.replace(reg,"$1$2'$3"));
          // 返回結(jié)果 MikeMike's

          非打印字符

          \s 任何空白字符。即[ \f\n\r\t\v]
          \S 任何非空白字符。
          \t Tab 字符(\u0009)。
          \n 換行符(\u000A)
          \v 垂直制表符(\u000B)。
          \f 換頁符(\u000C)
          \r 回車符(\u000D)。

          注意:\n\r一起使用,即 /[\r\n]/g來匹配換行,因?yàn)閡nix擴(kuò)展的系統(tǒng)以\n標(biāo)志結(jié)尾,window以\r\n標(biāo)志結(jié)尾。

          其他

          \cx 匹配 x 指示的控制字符,要求x 的值必須在 A-Z 或 a-z 范圍內(nèi)。
          \xn 匹配n,n 是一個十六進(jìn)制轉(zhuǎn)義碼,兩位數(shù)長。
          \un 匹配 n,其中n 是以四位十六進(jìn)制數(shù)表示的 Unicode 字符。

          \nm 或 \n 先嘗試反向引用,不可則再嘗試標(biāo)識為一個八進(jìn)制轉(zhuǎn)義碼。
          \nml 當(dāng)n 是八進(jìn)制數(shù)字 (0-3),m 和 l 是八進(jìn)制數(shù)字 (0-7) 時,匹配八進(jìn)制轉(zhuǎn)義碼 nml。

          修飾符

          • i 執(zhí)行不區(qū)分大小寫的匹配。

          • g 執(zhí)行一個全局匹配,簡而言之,即找到所有的匹配,而不是在找到第一個之后就停止。

          • m 多行匹配模式,^匹配一行的開頭和字符串的開頭,$匹配行的結(jié)束和字符串的結(jié)束。

          ES6新增u和y修飾符:

          • u修飾符

          含義為“Unicode模式”,用來正確處理大于\uFFFF的Unicode字符。也就是說,會正確處理四個字節(jié)的UTF-16編碼。

          // 加u修飾符以后,ES6就會識別\uD83D\uDC2A為一個字符,返回false。
          /^\uD83D/u.test('\uD83D\uDC2A')  // false
          /^\uD83D/.test('\uD83D\uDC2A') // true
          • y修飾符

          與g修飾符都是全局匹配,不同之處在于:lastIndex屬性指定每次搜索的開始位置,g修飾符從這個位置開始向后搜索,直到發(fā)現(xiàn)匹配為止;但是y修飾符要求必須在lastIndex指定的位置發(fā)現(xiàn)匹配,即y修飾符確保匹配必須從剩余的第一個位置開始,這也是“粘連”的涵義。

          /b/y.exec('aba')  // null 
          /b/.exec('aba')  // ["b"]

          優(yōu)先級順序:

          1. \ 轉(zhuǎn)義符

          2. (), (?:), (?=), [] 括號和中括號

          3. *、+、?、{n}、{n,}、{n,m} 限定符

          4. 任何元字符^、$、\ 定位點(diǎn)和序列

          5. | 替換

          關(guān)于引擎

          JS 是 NFA 引擎。

          NFA 引擎的特點(diǎn):

          • 以貪婪方式進(jìn)行,盡可能匹配更多字符。

          • 急于邀功請賞,所以最左子正則式優(yōu)先匹配成功,因此偶爾會錯過最佳匹配結(jié)果(多選條件分支的情況)。

          'nfa not'.match(/nfa|nfa not/)
          //  返回["nfa"]
          • 回溯(backtracking),導(dǎo)致速度慢。

          舉個貪婪與回溯結(jié)合的例子:

          "AB01CD23CD45CEff".match('AB.*CD')
          // 返回 ["AB01CD23CD"]

          匹配順序如圖所示:

          參考

          MDN
          w3school
          http://es6.ruanyifeng.com/#docs/regex
          http://imweb.io/topic/56e804ef1a5f05dc50643106
          http://www.cnblogs.com/deerchao/archive/2006/08/24/zhengzhe30fengzhongjiaocheng.html
          http://www.cnblogs.com/hustskyking/p/how-regular-expressions-work.html


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

          手機(jī)掃一掃分享

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

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  蜜桃av在线播放 免费超碰在线观看 | 久久99久久久久久久久久久 | 五月天Av成人在线播放 | 日韩一级视频 | 五月丁香婷中文 |