4

前言

作为一个程序员,要出去装逼,手中必备的技能就是正则表达式。程序员的正则表达式,医生的处方和道士的鬼画符,都是利器。

在js中,很多的场景需要去使用到它(毕竟,js刚刚诞生的时候,是用来做表单等验证的)。其实,正则表达式是一门语言,有自己独特的语法,还拥有自己的解释器。但是,作为使用来说,我们只需要掌握它的语法,多多运用,才能熟练。其实,我想过很多种详解表达式的方式,但是,似乎每种方式都有缺陷,因为正则表达式的语法需要记忆的部分比较多。最后,我觉得可以通过比较和分类的方式去记忆。如果你喜欢我的文章,欢迎评论,欢迎Star~。欢迎关注我的github博客

正文

创建

在正则表达式中,有两种方式可以去创建正则表达式:

  1. 字面量
const reg = /abc/;
  1. 构造函数
const reg = new RegExp('abc');

对于这两种方式,如果正则表达式是静态的,那么,使用第一种字面量的方式,性能会比较好。但是,如果正则表达式是动态的,是根据变量来定义的,那么,只能使用第二种构造函数的方式。

语法

  1. ^ 和 $的对比

    ^:匹配字符串的行首。示例说明:

    const reg = /^A/;
    
    console.log(reg.test('Ant'));    //true
    console.log(reg.test(' Ant'));       //false
$:匹配字符串的行尾。示例说明:
const reg = /t$/;

console.log(reg.test('eat'));       //true
console.log(reg.test('enter'));       //false
  1. 重复限定符(*、+、?、{n}、{n,}、{n, m})

    *:匹配前一个字符0次或多次,(x >= 0)

    const reg = /a*/;
    
    console.log(reg.test('ba'));      //true
    console.log(reg.test('b'));       //true
    console.log(reg.test('baaa'));     //true

    +:匹配前一个字符1次或多次,(x >= 1)

    const reg = /a+/;
    
    console.log(reg.test('ba'));    //true
    console.log(reg.test('baaa'));    //true
    console.log(reg.test('b'));     //false

    ?:匹配前一个字符的0次或1次,(x = 0 || x = 1)

    const reg = /ba?/;
    
    console.log(reg.exec('ba'));      //['ba']
    console.log(reg.exec('baaa'));      //['ba']
    console.log(reg.exec('b'));     //['b']

    注:这里只是指明了?字符的限定符方面的用法,它还可以控制贪婪模式和非贪婪模式(下文可见)

    {n}: 匹配前一个字符n次,(x = n)

    const reg = /ba{3}/;
    
    console.log(reg.test('ba'));     //false
    console.log(reg.test('baaa'));      //true
    console.log(reg.test('b'));     //false

    {n,}:匹配前一个字符n次或大于n次,(x >=n)

    const reg = /ba{3,}/;
    
    console.log(reg.test('ba'));     //false
    console.log(reg.test('baaa'));      //true
    console.log(reg.test('baaaa'));      //true
    console.log(reg.test('b'));      //false

    {n, m}:匹配前一个字符n次到m次之间,(n <= x <= m)

    const reg = /ba{2,3}/;
    
    console.log(reg.test('ba'));     //false
    console.log(reg.test('baaa'));     //true
    console.log(reg.test('baa'));     //true
    console.log(reg.test('b'));      //false
  2. 元字符(. 、d、w、s、b)

    . :匹配除换行符以外的所有字符

    const reg = /b.?/;
    
    console.log(reg.exec('ba'));     //['ba']
    console.log(reg.exec('bxaa'));      //['bx']
    console.log(reg.exec('bza'));     //['bz']
    console.log(reg.exec('b'));      //['b']

    \d:匹配数字字符,与[0-9]一致(单词记忆法 => 数字【digital】)

    const reg = /b\d/;
    
    console.log(reg.exec('b1'));       //['b1']
    console.log(reg.exec('b2aa'));      //['b2']
    console.log(reg.exec('bza'));      //null
    console.log(reg.exec('b'));        //null

    \w:匹配字母、数字和下划线(单词记忆法 => 单词【word】)

    const reg = /b\w/;
    
    console.log(reg.exec('b1'));     //['b1']
    console.log(reg.exec('b2aa'));     //['b2']
    console.log(reg.exec('bza'));      //['bz']
    console.log(reg.exec('b'));       //null

    \b:匹配一个边界,一个独立单词的开头或结尾(单词记忆法 => 边界【border】)

    const str = 'moon is white';
    
    console.log(str.match(/\bm/));     //['m']
    console.log(str.match(/oon\b/));     //['oon']

    \s:匹配空白符(空格、换行符、制表符)(单词记忆法 => 符号【space】)

    const str = 'moon is white';
    
    console.log(str.match(/is\swhite/));    //['is white']
    console.log(str.match(/moon\sis/));    // ['moon is']
  3. 反元字符([^x]、\D、\W、\B、\S)

    [^x]:匹配除x之外的任意字符

    const reg = /b[^a]/;
    
    console.log(reg.exec('ba'));     //null
    console.log(reg.exec('bz'));     //['bz']
    console.log(reg.exec('by'));    //['by']

    \D:匹配除数字之外的任意字符,与d相反

    const reg = /b\D/;
    
    console.log(reg.exec('b1'));    //null
    console.log(reg.exec('b2'));    //null
    console.log(reg.exec('by'));     //['by']

    \W:匹配除数字、字母和下划线以外的任意字符,与w相反

    const reg = /b\W/;
    
    console.log(reg.exec('b1'));     //null
    console.log(reg.exec('ba'));     //null
    console.log(reg.exec('b_'));      //null
    console.log(reg.exec('b*'));      //['b*']

    \B:匹配非单词边界的字符,与b相反

    const str = 'moon is white';
    
    console.log(str.match(/\Boon/));     //['oon']
    console.log(str.match(/whit\B/));      //['whit']

    \S:匹配非空白字符,与s相反

    const str = 'moon is white';
    
    console.log(str.match(/mo\Sn/));    //['moon']
    console.log(str.match(/whit\S/));      //['white']
  4. 字符组([...])

    [...]:匹配方括号中的字符集合,例如[0-9] => 匹配数字字符

    const reg = /b[a-z]/;
    
    console.log(reg.test('ba'));      //true
    console.log(reg.test('bA'));       //false
  5. 分组((...))

    (X):将括号中的字符看成一个组进行匹配,例如(ab)+ => 可以匹配'ababab'

    const reg = /(abab)+/;
    
    console.log(reg.exec('ababab'));     //['abab', 'abab']
    console.log(reg.exec('abababab'));   //['abababab','abab']

    (?:X):匹配X,但是不记录匹配项。而上面的(X)是记录匹配项的。
    (?=X):正向肯定查找,即匹配后面紧跟X的字符串。

    const reg = /\d+(?=\.)/;
    
    console.log(reg.exec('3.141'))  //['3']

(?!X):正向否定查找,即匹配后面不跟X的字符串,与(?:X)相反。

const reg = /\d+(?!\.)/;

console.log(reg.exec('3.141'))   //['141']
  1. 多选符 (|)

    |:匹配两者中的一个,例如a|b => 匹配a或b

    const reg = /a|b/;
    
    console.log(reg.exec('a'));     //['a']
    console.log(reg.exec('b'));     //['b']
    console.log(reg.exec('c'));      //['c']
  2. 转移字符()

    :表示转义字符,将特殊的字符转义成普通字符进行匹配

匹配方式

匹配方式,即正则表达式在匹配过程中,当具备多个结果时,按照一定的模式进行匹配。

匹配方式可分为两种,贪婪模式和非贪婪模式。

贪婪模式:即以限定符最大重复标准进行匹配。例如:使用/ba*/匹配'baaaaa'时,结果可返回'baaaaa'

非贪婪模式:即以限定符最小重复标准进行匹配。例如:使用/ba*?/匹配'baaaaa'时,结果可返回'b'

const str = 'baaaaa';

console.log(str.match(/ba*/));           //['baaaaa']
console.log(str.match(/ba*?/));        //['b']

其中?符号起到了贪婪与非贪婪模式之间的转变,在重复限定符后加上?,按非贪婪模式进行匹配;默认为贪婪模式。

标识方式

标识方式,就是正则表达式后面跟的匹配方式,flag

g:全局匹配,记忆方式【global】

i:忽略大小写,记忆方式【ignore】

m:多行搜索,记忆方式【multline】

方法

使用正则表达式的方式一共有6种,可以分成:reg有两种,string有四种。

首先,我们来看一下reg对象带的两种方法:exec和test

  1. test => 判断字符串中是否存在与正则表达式匹配的字符串,返回boolean类型

测试用例:

const reg = /abc/;

console.log(reg.test('abca'));     //true
console.log(reg.test('abac'));     //false
  1. exec => 匹配字符串中满足条件的字符串,返回一个匹配的结果数组
const reg = /\d+/;

console.log(reg.exec('1234dhi343sf2'));    //['1234']

之后是string的四种方法:match、search、replace、split

  1. match:查找字符串中的匹配的字符串,返回一个结果数组,若没有匹配则返回null
const str = 'this is reg expression test'

console.log(str.match(/\bi.\s\w+/)); //['is reg']
  1. search:查找字符串中匹配的字符串,返回匹配字符串的下标,若没有匹配则返回-1
const str = 'this is reg expression test'

console.log(str.search(/\bi.\s\w+/));    //5
  1. replace:查找字符串中匹配的字符串,对其进行替换(这是一个个人觉得比较厉害的技能)

    • 接收字符串
    var str = 'this is reg expression test'
    
    console.log(str.replace(/\b(i.)\s(\w+)/, '$1 hello $2'));    //'this is hello reg expression test'
    • 接收函数
    var str = 'this is reg expression test'
    
    str.replace(/\b(i.)\s(\w+)/, (...args) => {
       console.log(args);
    });    //["is reg", "is", "reg", 5, "this is reg expression test"]

注:这个函数会有一些参数,第一个是匹配的字符串,第二个是第一项匹配的,第三个是第二项匹配的,第四个是匹配的下标,第五个是原字符串

  1. split:使用正则表达式或者固定字符,分割字符串
var str = 'this is reg expression test'

console.log(str.split(/\s/))   //["this", "is", "reg", "expression", "test"]

总结

js部分的正则表达式很多东西都以及讲完了,剩下的就是练习了。这种记忆性的东西,需要不断的使用,才会孰能生巧。下面部分提供一下练习的语句,答案在js正则表达式练习整理

如果你对我写的有疑问,可以评论,如我写的有错误,欢迎指正。你喜欢我的博客,请给我关注Star~呦。大家一起总结一起进步。欢迎关注我的github博客


zimo
2.2k 声望167 粉丝

no regrets yesterday, more struggling today, looking forward to tomorrow