JS 正则表达式总结

0、前言

  作为一名前端开发者,在做表单验证或者写一些gulp任务或webpack配置时都不可避免的会用到正则,虽然零零散散看过一些正则相关语法,但始终觉得没吃透,直到遇到这篇文章(强烈推荐)。本文仅记录个人觉得很有价值的几个点。

1、正则语法

正则是匹配模式,要么匹配字符,要么匹配位置。

对于一个字符串string='hello',你应该这样看待它:


也就是要看成字符和位置的集合,而不是单单的是字符。

  • 字符组
    范围表示法:[a-z]从a到z的所有小写字母;
    排除字符组:[^a-z]除a-z以外的所有字符;
    常见缩写:\d,\D,\w,\W,\s,\S,.,其中'.'匹配任意非换行符、回车符、行分隔符和段分隔符。
    此外,若要匹配任意字符,可用:[\d\D]、[\w\W]、[\s\S]和[^]中任何的一个。

  • 多选分支

    (p1|p2|p3),其中p1、p2和p3是子模式,用|(管道符)分隔,表示其中任何之一

    注意:分支结构是惰性的,当第一个子模式匹配成功后,后面的模式会被忽略

  • 位置匹配符(6个)

    ^ $ \b \B (?=p) (?!p)

    ^:开始的位置;
    $:结束的位置;
    \b:单词边界,具体就是\w和\W之间的位置,也包括\w和^之间的位置,也包括\w和$之间的位置;
    \B:\b的取反;
    (?=p):p之前的位置,正向先行断言;
    (?!p):上述取反,反向先行断言;
    把位置理解空字符,是对位置非常有效的理解方式。同一个位置可以有多个空字符,就像^和首字母之间还可以有其它空位置一样

  • 括号的作用
    1、分组和分支

    /(ab)+/         //分组
    /^I love (JavaScript|Regular Expression)$/       //分支
    

    2、分组引用
    主要是方便获取小括号匹配到的内容

    //1、match方法,有小括号时,返回的数组中包含小括号匹配的内容
    var regex = /(\d{4})-(\d{2})-(\d{2})/;
    var string = "2017-06-12";
    console.log( string.match(regex) ); 
    // => ["2017-06-12", "2017", "06", "12", index: 0, input: "2017-06-12"]
    
    //2、API引用法,使用replace时可直接用$1等获取小括号内容
    var regex = /(\d{4})-(\d{2})-(\d{2})/;
    var string = "2017-06-12";
    regex.test(string); // 正则操作即可,例如
    //regex.exec(string);
    //string.match(regex);
    console.log(RegExp.$1); // "2017"
    console.log(RegExp.$2); // "06"
    console.log(RegExp.$3); // "12"
    
    //3、反向引用 \1,\2
    var regex = /\d{4}(-|\/|\.)\d{2}\1\d{2}/;
    var string1 = "2017-06-12";
    var string2 = "2017/06/12";
    var string3 = "2017.06.12";
    var string4 = "2016-06/12";
    console.log( regex.test(string1) ); // true
    console.log( regex.test(string2) ); // true
    console.log( regex.test(string3) ); // true
    console.log( regex.test(string4) ); // false
    

    3、非捕获分组
    非捕获分组的意义在于不引用括号的内容,节省内存

    var regex = /(?:ab)+/g;
    var string = "ababa abbb ababab";
    console.log( string.match(regex) ); 
    //=>RegExp.$1值为'''',不用非捕获模式时为"ab"
    
  • 符号的优先级
    一个正则表达式涉及的操作符有:

    1.转义符 \
    2.括号和方括号 (...)、(?:...)、(?=...)、(?!...)、[...]
    3.量词限定符 {m}、{m,n}、{m,}、?、*、+
    4.位置和序列 ^ 、$、 \元字符、 一般字符

    1. 管道符(竖杠)|.

    上面操作符的优先级从上至下,由高到低。

2、写好正则的建议

  • 使用具体型字符组来代替通配符,来消除回溯
    少用通配符'.',减少回溯次数,提升匹配速度
  • 使用非捕获型分组(?:)
    当必须要用括号,又不想引用时,使用非捕获型分组可节省内存
  • 独立出确定字符
    例如/a+/,可以修改成/aa*/。后者能比前者多确定了字符a,可加快判断是否匹配失败,进而加快移位的速度
  • 提取分支公共部分
    比如/abc|def/,修改成/^(?:abc|def)/。这样做,可以减少匹配过程中可消除的重复。
  • 减少分支的数量,缩小它们的范围
    /red|read/,可以修改成/rea?d/。此时分支和量词产生的回溯的成本是不一样的。

3、正则相关JS函数

String类型四个+RegExp类型二个,常用的是3+1

  • match
    当全局匹配时,match返回所有匹配结果,数组形式;
    当局部匹配时,match返回一个结果和其它信息,如index,input,数组形式;
    当没有匹配到数据时,返回null

    var string = "2017.06.27";
    var regex1 = /\b(\d+)\b/;
    var regex2 = /\b(\d+)\b/g;
    console.log( string.match(regex1) );
    console.log( string.match(regex2) );
    // => ["2017", "2017", index: 0, input: "2017.06.27"]
    // => ["2017", "06", "27"]
    
  • split
    1、接受第二个参数,表示分割后数组的长度;
    2、和match一样,当第一个参数是字符串时会将其转为正则表达式,因此建议不要传字符串,而是直接传正则

  • replace
    1、第二个参数可以是字符串或者函数,当是函数时,第一个参数表示整个匹配的内容,然后依次是括号匹配的内容,再然后是index和input;
    2、str.replace返回的是新字符串,str本身并未被改变,即replace是不改变原始字符串的。

  • test

    /\d+/.test(123);//true
    

4、总结

本文是结合自身情况对老姚的这篇文章进行的总结。收获如下:

  • 操作符优先级:转义>括号>量词>普通字符>管道符
  • 正则表达式不光匹配字符,还匹配位置
  • 位置符:^ $ (?=b) (?!b) \b \B,其中\b是\w与\W之间的位置,(?=b)是b之前的位置
  • ^与首字母之间还可以有位置,尾字母和$同理。即同一个位置可以有多个空白字符。
  • 写好正则的建议 -第二节

5、案例

  • 把"12345678",变成"12,345,678"
var string1 = "12345678",
string2 = "123456789";
reg = /(?!^)(?=(\d{3})+$)/g;

var result = string1.replace(reg, ',')
console.log(result); 
// => "12,345,678"

result = string2.replace(reg, ',');
console.log(result); 
// => "123,456,789"

(?!^) 表示非开头的位置
(?=(\d{3})+$) 表示从结尾的位置开始往前连续三个数字之前的位置

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

推荐阅读更多精彩内容