<dl id="3wz6h"></dl><li id="3wz6h"></li>

      1. <dl id="3wz6h"></dl>

      2. <dl id="3wz6h"><ins id="3wz6h"></ins></dl>

            <dl id="3wz6h"></dl>

            <dl id="3wz6h"><ins id="3wz6h"></ins></dl>
            1. 
              
              <output id="3wz6h"><ins id="3wz6h"><nobr id="3wz6h"></nobr></ins></output>

              <li id="3wz6h"><ins id="3wz6h"></ins></li>
              
              

            2. <output id="3wz6h"><ins id="3wz6h"><nobr id="3wz6h"></nobr></ins></output>
              首頁»JavaScript»系統認識JavaScript正則表達式

              系統認識JavaScript正則表達式

              來源:唐金健 發布時間:2018-05-27 閱讀次數:

              一、正則表達式簡介

              1、什么是正則表達式

              正則表達式,又稱規則表達式。(英語:Regular Expression,在代碼中常簡寫為regex、regexp或RE),計算機科學的一個概念。正則表達式通常被用來檢索、替換那些符合某個模式(規則)的文本。

              簡單的說,就是按照某種規則去匹配符合條件的字符串。

              2、可視化正則表達式工具

              Regexper:https://regexper.com/

              二、RegExp對象

              實例化RegExp的兩種方式。

              兩種方式定義RegExp對象。

              1、字面量

              let reg = /[a-z]{3}/gmi;
              let reg = /[a-z]{3}/g;
              let reg = /[a-z]{3}/m;
              let reg = /[a-z]{3}/i;

              標志

              • g global 代表全局搜索。如果不添加,搜索到第一個匹配停止。
              • m Multi-Line 代表多行搜索。
              • i ignore case 代表大小寫不敏感,默認大小寫敏感。

              2、構造函數

              let reg = new RegExp('\\bis\\b', 'g');

              因為JavaScript字符串中\屬于特殊字符,需要轉義。

              三、元字符

              把元字符當作轉義字符。

              正則表達式有兩種基本字符類型組成。

              • 原義文本字符
              • 元字符

              1、原義文本字符

              表示原本意義上是什么字符,就是什么字符。

              2、元字符

              是在正則表達式中有特殊含義的非字母字符。
              * + ? $ ^ . | \ ( ) { } [ ]

              字符 含義
              \t 水平制表符
              \v 垂直制表符
              \n 換行符
              \r 回車符
              \0 空字符
              \f 換頁符
              \cX 控制字符,與X對應的控制字符(Ctrl + X)

              類似于轉義字符。

              四、字符類

              表示符合某種特性的字符類別。

              使用元字符[]可以構建一個簡單的類。
              所謂類是指符合某些特性的對象,一個泛指,而不是某個字符。

              例子

              表達式[abc]把字符abc歸為一類,表達式可以匹配這一類中的任意一個字符。

              // replace() 方法用于在字符串中用一些字符替換另一些字符,或替換一個與正則表達式匹配的子串。
              'a1b2c3d4e5'.replace(/[abc]/g, '0');  //010203d4e5

              字符類取反

              我們想要替換不是abc中任意一個字符的字符。

              // 元字符 ^ 創建一個 反向類/負向類
              'abcdefg'.replace(/[^abc]/g, '0');  //abc0000

              五、范圍類

              匹配這一個范圍內的字符。

              如果我們想要匹配數字0-9,那么我們可能會這樣寫[0123456789]
              如果我們想要匹配26個字母,那么我們可能會這樣寫[abcdefghijklmnopqrstuvwxyz]
              這樣略顯麻煩,所以才會有范圍類。

              例子

              // 替換所有數字
              'a1c2d3e4f5'.replace(/[0-9]/g, 'x');  //axcxdxexfx
              // 替換所有小寫字母
              'a1c2d3e4f5'.replace(/[a-z]/g, 'x');  //x1x2x3x4x5
              // []組成的類內部是可以連寫的。替換所有大小寫字母
              'a1C2d3E4f5G6'.replace(/[a-zA-Z]/g, '*');  //*1*2*3*4*5*6

              疑問

              如果我想替換數字,并且連帶-符號也一起替換呢?

              // 替換所有數字和橫杠
              '2018-5-21'.replace(/[0-9-]/g, '*');  //*********

              六、預定義類

              一些已經定義的類,可以直接使用。
              字符 等價類 含義
              . [^\r\n] 除了回車、換行之外的所有字符
              \d [0-9] 數字字符
              \D [^0-9] 非數字字符
              \s [\t\n\x0B\r] 空白符
              \S [^\t\n\x0B\r] 非空白符
              \w [a-zA-Z_0-9] 單詞字符(字母、數字、下劃線)
              \W [^a-zA-Z_0-9] 非單詞字符

              例子

              替換一個 ab + 數字 + 任意字符 的字符串

              // 寫法1
              'ab0c'.replace(/ab[0-9][^\r\n]/g, 'TangJinJian');  //TangJianJian
              // 寫法2
              'ab0c'.replace(/ab\d./g, 'TangJinJian');  //TangJianJian

              七、單詞邊界

              字符 含義
              ^ 以xxx開始(不在中括號內時的含義)
              $ 以xxx結束
              \b 單詞邊界
              \B 非單詞邊界

              例子

              我想替換的字符串,屬于那種只在開頭出現的。

              'YuYan is a boy, YuYan'.replace(/^YuYan/g, 'TangJinJian');  //TangJinJian is a boy, YuYan

              我想替換的字符串,屬于那種只在結尾出現的。

              'YuYan is a boy, YuYan'.replace(/YuYan$/g, 'TangJinJian');  //YuYan is a boy, TangJinJian

              單詞邊界例子。

              // 替換所有is為0
              'This is a man'.replace(/is/g, '0');  //Th0 0 a man
              // 替換所有is前面帶有單詞邊界的字符串
              'This is a man'.replace(/\bis/g, '0');  //This 0 a man
              // 替換所有is前面沒有單詞邊界的字符串
              'This is a man'.replace(/\Bis\b/g, '0');  //Th0 is a man

              八、量詞

              用來處理連續出現的字符串。
              字符 含義
              ? 出現零次或一次(最多出現一次)
              + 出現一次或多次(至少出現一次)
              * 出現零次或多次(任意次)
              {n} 出現n次
              {n,m} 出現n到m次
              {n,} 至少出現n次

              我想替換字符串中連續出現10次的數字為*

              '1234567890abcd'.replace(/\d{10}/, '*');  //*abcd

              我想替換字符串中的QQ號碼。

              '我的QQ是:10000'.replace(/[1-9][0-9]{4,}/, '19216811');  //我的QQ是:19216811

              九、貪婪模式

              盡可能多的匹配。

              有這樣的一種場景下的正則表達式,/\d{3,6}/該替換3個數字還是6個數字呢,4、5個數字?

              // 貪婪模式會盡可能的往多的方面去匹配
              '123456789'.replace(/\d{3,6}/, 'x');  //x789
              '123456789'.replace(/\d+/, 'x');  //x
              '123456789'.replace(/\d{3,}/, 'x');  //x

              十、非貪婪模式

              盡可能少的匹配。

              如果我們想要最低限度的替換呢?

              // 非貪婪模式使用 ? 盡可能的往少的方面去匹配
              '12345678'.replace(/\d{3,6}?/g, 'x');  //xx78
              '123456789'.replace(/\d{3,6}?/g, 'x');  //xxx

              因為有g標志,會匹配這段字符串里所有符合規則的字符串。
              第一個規則/\d{3,6}?/g12345678中有兩個符合條件的字符串,是123456。所以替換結果是xx78
              第二個規則/\d{3,6}?/g123456789中有三個符合條件的字符串,是123456789。所以替換結果是xxx

              十一、分組

              括號里的一些規則,分為一組。

              我想替換連續出現3次的字母數字

              //沒有分組的情況下,后面的量詞,只是表示匹配3次數字。
              'a1b2d3c4'.replace(/[a-z]\d{3}/g, '*');  //a1b2d3c4
              //有分組的情況下,分組后面的量詞,表示符合這個分組里規則的字符串,匹配3次。
              'a1b2d3c4'.replace(/([a-z]\d){3}/g, '*');  //*c4

              1、或

              分組里有兩種規則,只要滿足其中一種即可匹配。

              //我想把ijaxxy和ijcdxy都替換成*
              'ijabxyijcdxy'.replace(/ij(ab|cd)xy/g, '*');  //**

              2、反向引用

              可以把分組視為變量,來引用。

              //我想把改變年月日之間的分隔符
              '2018-5-22'.replace(/(\d{4})-(\d{1,2})-(\d{1,2})/g, '$1/$2/$3');  //2018/5/22
              //我想替換日期,并且更改順序
              '2018-5-22'.replace(/(\d{4})-(\d{1,2})-(\d{1,2})/g, '$2/$3/$1');  //5/22/2018

              3、忽略分組

              忽略掉分組,不捕獲分組,只需要在分組內加上?:

              // 忽略掉匹配年的分組后,匹配月的分組變成了$1,日的分組變成了$2
              '2018-5-22'.replace(/(?:\d{4})-(\d{1,2})-(\d{1,2})/g, '$1/$2/$3');  //5/22/$3

              十二、前瞻

              正則表達式從文本頭部向尾部開始解析,文本尾部方向,稱為“前”。
              前瞻就是在正在表達式匹配到規則的時候,向前檢查是否符合斷言,后顧/后瞻方向相反。
              JavaScript不支持后顧。
              符合和不符合特定斷言稱為肯定/正向匹配和否定/負向匹配。
              名稱 正則 含義
              正向前瞻 exp(?=assert)  
              負向前瞻 exp(?!assert)  
              正向后顧 exp(?<=assert) JavaScript不支持
              負向后顧 exp(?<!assert) JavaScript不支持

              例子

              有這樣一個單詞字符+數字格式的字符串,只要滿足這種格式,就把其中的單詞字符替換掉。

              'a1b2ccdde3'.replace(/\w(?=\d)/g, '*');  //*1*2ccdd*3

              有這樣一個單詞字符+非數字格式的字符串,只要滿足這種格式,就把前面的單詞字符替換掉。

              'a1b2ccdde3'.replace(/\w(?!\d)/g, '*');  //a*b*****e*

              十三、RegExp對象屬性

              global是否全文搜索,默認false
              ignore case是否大小寫敏感,默認是false
              multiline多行搜索,默認值是false
              lastIndex是當前表達式匹配內容的最后一個字符的下一個位置。
              source正則表達式的文本字符串。

              let reg1 = /\w/;
              let reg2 = /\w/gim;
              
              reg1.global;  //false
              reg1.ignoreCase;  //false
              reg1.multiline;  //false
              
              reg2.global;  //true
              reg2.ignoreCase;  //true
              reg2.multiline;  //true

              十四、RegExp對象方法

              1、RegExp.prototype.test()

              用來查看正則表達式與指定的字符串是否匹配。返回truefalse
              let reg1 = /\w/;
              reg1.test('a');  //true
              reg1.test('*');  //false

              加上g標志之后,會有些區別。

              let reg1 = /\w/g;
              // 第一遍
              reg1.test('ab');  //true
              // 第二遍
              reg1.test('ab');  //true
              // 第三遍
              reg1.test('ab');  //false
              // 第四遍
              reg1.test('ab');  //true
              // 第五遍
              reg1.test('ab');  //true
              // 第六遍
              reg1.test('ab');  //false

              實際上這是因為RegExp.lastIndex。每次匹配到之后,lasgIndex會改變。
              lastIndex是正則表達式的一個可讀可寫的整型屬性,用來指定下一次匹配的起始索引。

              let reg = /\w/g;
              // 每次匹配到,就會把lastIndex指向匹配到的字符串后一個字符的索引。
              while(reg.test('ab')) {
                  console.log(reg.lastIndex);
              }
              // 1
              // 2

              reg.lastIndex初始時為0,第一個次匹配到a的時候,reg.lastIndex1。第二次匹配到b的時候,reg.lastIndex2

              let reg = /\w\w/g;
              while(reg.test('ab12cd')) {
                console.log(reg.lastIndex);
              }
              // 2
              // 4
              // 6

              reg.lastIndex初始時為0,第一個次匹配到ab的時候,reg.lastIndex2。第二次匹配到12的時候,reg.lastIndex4。第三次匹配到cd的時候,reg.lastIndex6

              let reg = /\w/g;
              // 匹配不到符合正則的字符串之后,lastIndex會變為0。
              while(reg.test('ab')) {
                  console.log(reg.lastIndex);
              }
              console.log(reg.lastIndex);
              reg.test('ab');
              console.log(reg.lastIndex);
              // 1
              // 2
              // 0
              // 1

              所以,這就是為什么reg.test('ab')再多次執行之后,返回值為false的原因了。

              let reg = /\w/g;
              reg.lastIndex = 2;
              reg.test('ab');  //false

              每次匹配的起始位置,是以lastIndex為起始位置的。上述例子,一開始從位置2開始匹配,位置2后面沒有符合正則的字符串,所以為false

              2、RegExp.prototype.exec()

              在一個指定字符串中執行一個搜索匹配。返回一個搜索的結果數組或null

              非全局情況

              let reg = /\d(\w)\d/;
              let ts = '*1a2b3c';
              let ret = reg.exec(ts);  //ret是結果數組
              // reg.lastIndex肯定是0,因為沒有g標志。 沒有g標志的情況下,lastIndex被忽略。
              console.log(reg.lastIndex + '\t' + ret.index + '\t' + ret.toString());
              console.log(ret);
              // 0  1 1a2,a
              // ["1a2", "a"]

              返回數組是有以下元素組成的:

              • 第一個元素是與正則表達式相匹配的文本。
              • 第二個元素是reg對象的第一個子表達式相匹配的文本(如果有的話)。
              • 第二個元素是reg對象的第二個子表達式相匹配的文本(如果有的話),以此類推。
              // 子表達式就是分組。
              let reg = /\d(\w)(\w)(\w)\d/;
              let ts = '*1a2b3c';
              let ret = reg.exec(ts);
              console.log(reg.lastIndex + '\t' + ret.index + '\t' + ret.toString());
              console.log(ret);  //輸出結果數組
              // 0  1 1a2b3,a,2,b
              // ["1a2b3", "a", "2", "b"]

              全局情況

              let reg = /\d(\w)(\w)(\w)\d/g;
              let ts = '*1abc25def3g';
              while(ret = reg.exec(ts)) {
                  console.log(reg.lastIndex + '\t' + ret.index + '\t' + ret.toString());
              }
              // 6  1 1abc2,a,b,c
              // 11 6 5def3,d,e,f

              第一次匹配的是1abc21abc2的后一個字符的起始位置是6,所以reg.lastIndex6
              1abc2的第一個字符的起始位置是1,所以ret.index1

              第二次匹配的是5def35def3的后一個字符的起始位置是11,所以reg.lastIndex11
              5def3的第一個字符的起始位置是6,所以ret.index6

              十五、字符串對象方法

              1、String.prototype.search()

              執行正則表達式和String對象之間的一個搜索匹配。
              方法返回第一個匹配項的index,搜索不到返回-1
              不執行全局匹配,忽略g標志,并且總是從字符串的開始進行檢索。

              我想知道Jin字符串的起始位置在哪里。

              'TangJinJian'.search('Jin');  //4
              'TangJinJian'.search(/Jin/);  //4

              search方法,既可以通過字符串,也可以通過正則描述字符串來搜索匹配。

              2、String.prototype.match()

              當一個字符串與一個正則表達式匹配時, match()方法檢索匹配項。
              提供RegExp對象參數是否具有g標志,對結果影響很大。

              非全局調用的情況

              如果RegExp沒有g標志,那么match只能在字符串中,執行一次匹配。
              如果沒有找到任何匹配文本,將返回null
              否則將返回一個數組,其中存放了與它找到的匹配文本有關的信息。

              let reg = /\d(\w)\d/;
              let ts = '*1a2b3c';
              let ret = ts.match(reg);
              console.log(ret.index + '\t' + reg.lastIndex);
              console.log(ret);
              // 1  0
              // ["1a2", "a"]

              非全局情況下和RegExp.prototype.exec()方法的效果是一樣的。

              全局調用的情況

              我想找到所有數字+單詞+數字格式的字符串。

              let reg = /\d(\w)\d/g;
              let ts = '*1a2b3c4e';
              let ret = ts.match(reg);
              console.log(ret.index + '\t' + reg.lastIndex);
              console.log(ret);
              // undefined  0
              // ["1a2", "3c4"]

              全局情況下和RegExp.prototype.exec()方法的區別。在于,沒有了分組信息。
              如果我們不使用到分組信息,那么使用String.prototype.match()方法,效率要高一些。而且不需要寫循環來逐個所有的匹配項獲取。

              3、String.prototype.split()

              使用指定的分隔符字符串將一個String對象分割成字符串數組。
              'a,b,c,d'.split(/,/);  //["a", "b", "c", "d"]
              'a1b2c3d'.split(/\d/);  //["a", "b", "c", "d"]
              'a1b-c|d'.split(/[\d-|]/);  //["a", "b", "c", "d"]

              4、String.prototype.replace()

              返回一個由替換值替換一些或所有匹配的模式后的新字符串。模式可以是一個字符串或者一個正則表達式, 替換值可以是一個字符串或者一個每次匹配都要調用的函數。

              常規用法

              'TangJinJian'.replace('Tang', '');  //JinJian
              'TangJinJian'.replace(/Ji/g, '*');  //Tang*n*an

              以上兩種用法,是最常用的,但是還不能精細化控制。

              精細化用法

              我想要把a1b2c3d4中的數字都加一,變成a2b3c4d5

              'a1b2c3d4'.replace(/\d/g, function(match, index, orgin) {
                  console.log(index);
                  return parseInt(match) + 1;
              });
              // 1
              // 3
              // 5
              // 7
              // a2b3c4d5

              回調函數有以下參數:

              • match第一個參數。匹配到的字符串。
              • group第二個參數。分組,如果有n個分組,則以此類推n個group參數,下面兩個參數將變為第2+n3+n個參數。沒有分組,則沒有該參數。
              • index第三個參數。匹配到的字符串第一個字符索引位置。
              • orgin第四個參數。源字符串。

              我想把兩個數字之間的字母去掉。

              'a1b2c3d4e5f6'.replace(/(\d)(\w)(\d)/g, function(match, group1, group2, group3, index, orgin) {
                console.log(match);
                return group1 + group3;
              });
              // 1b2
              // 3d4
              // 5f6
              // a12c34e56
              QQ群:WEB開發者官方群(515171538),驗證消息:10000
              微信群:加小編微信 849023636 邀請您加入,驗證消息:10000
              提示:更多精彩內容關注微信公眾號:全棧開發者中心(fsder-com)
              網友評論(共0條評論) 正在載入評論......
              理智評論文明上網,拒絕惡意謾罵 發表評論 / 共0條評論
              登錄會員中心
              云南十一选往期