正则表达式详解 js

前言

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

在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
    
  2. 重复限定符(*、+、?、{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
    
  3. 元字符(.、\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']
    
  4. 反元字符([^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']
    
  5. 字符组([...])

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

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

    (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']
    
  7. 多选符 (|)

    |:匹配两者中的一个,例如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']
    
  8. 转移字符(\)

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

匹配方式

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

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

贪婪模式:即以限定符最大重复标准进行匹配。例如:使用/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博客

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容