正则表达式

转义字符

let str = '<div>a</div>\
  <div>b</div>'
console.log(str);     // js只允许当行字符串,这里的 \ 是把后面的空格转义
\n  换行
\r   回车
\t

正则的两种写法及应用


var  reg = new RegExp('abc', 'igm');
var reg = /abc/igm;

应用:一般使用对象字面量(第二种)
let rule = 'abc';
var  reg = new RegExp(rule, 'igm');    // 要使用变量的情况下就要使用第一种情况,因为对象字面量会把rule当作一个字符串

正则修饰符/正则属性

  1. i: 忽略大小写
  2. g:全局匹配
  3. m: 多行匹配
const reg = /^test/;    
const str = 'abcasfdas \ntestasdasd';
console.log(reg.test(str));     // false
const reg2 = /^test/m;
console.log(reg2.test(str));   // true

方括号[] 参考: https://www.w3school.com.cn/jsref/jsref_obj_regexp.asp

[abc]: 取abc中的任意一个
[^abc]: 取非abc的任意一个, ^ 在 [] 是 非 的意思
/abc|123/g: 取 abc 或者 123

练习:我们要匹配 abc 或者 123 后再跟一位字母 q 
/abc|123q/g    //这样写是错误的,会匹配为 abc 或者 23q
/(abc|123)q/   // ()会提升优先级,先执行()里面的

量词 参考: https://www.w3school.com.cn/jsref/jsref_obj_regexp.asp

参考文档很详细,这里不多描述,只讲一些注意点

var str = "abcd";
var reg = /\w+/g;
var reg = /\w*/g;
console.log(str.match(reg));   // ["abcd"]
console.log(str.match(reg2));  // ["abcd", ""]   *是0到多次,匹配到 abcd 后,还会匹配一次 ""

练习
var str = "abcd";
var reg = /\d*/g;
console.log(str.match(reg));   // ["", "", "", "", ""]

var str = "abcd";
var reg = /\w?/g;
console.log(str.match(reg));   //  ["a", "b", "c", "d", ""]

子表达式,反向引用 (\n) ()除了提升权重外,还表示子表达式

        let str = 'aabbbbaaaabbbbwxxxxiaaaa';
        let reg = /(a)(b)\2\2\2/g;    // \n的n并不是数量,而是第几个引用,这里\1引用的就是a,\2引用就是b
        console.log(str.match(reg));

        let reg2 = /(\w)\1\1\1/g;       // 这样可以匹配到所有 aaaa bbbb cccc 这种格式
        console.log(str.match(reg2));

        let reg3 = /(\w)\1(\w)\2/g;       // 这样可以匹配到所有 aaaa bbbb cccc 这种格式
        console.log(str.match(reg3));     // 匹配 aabb xxyy 这种格式

贪婪模式和非贪婪模式

       {
            let str = "abc{{name}}safds{{age}}";
            let reg = /{{(.*)}}/g;
            console.log(reg.exec(str));  // "{{name}}safds{{age}}"  贪婪匹配,
            let reg2 = /{{(.*?)}}/g;
            console.log(str.match(reg2));  // ["{{name}}", "{{age}}"]    ?表示0或一次,但是在一些不是具体的量词(如+?*)后面表示 非贪婪匹配,能少匹配就不会多匹配
        }

        {
            let str = 'abcds';
            let reg = /\w??/g;
            console.log(str.match(reg));   // ["", "", "", "", "", ""]
        }

属性

  1. global:正则是否设置了全局匹配,return Boolean
  2. ignoreCase
  3. multiline]
  4. source : 返回正则的匹配规则
  5. lastIndex:一个整数,标示开始下一次匹配的字符位置。(与exec中结合讲解)

方法

  1. test() return Boolean
  2. exec()
            全局匹配的情况下
            let str = 'ababab';
            let reg = /ab/g;
            console.log(reg.lastIndex);   // 0
            console.log(reg.exec(str));   // ["ab", index: 0, input: "ababab", groups: undefined]
            console.log(reg.lastIndex);   // 2
            console.log(reg.exec(str));   // ["ab", index: 2, input: "ababab", groups: undefined]
            console.log(reg.lastIndex);   // 4
            console.log(reg.exec(str));   // ["ab", index: 4, input: "ababab", groups: undefined]
            console.log(reg.lastIndex);   // 6      // 这里是6的原因是开始下一次匹配的字符位置
            console.log(reg.exec(str));   // null
            console.log(reg.lastIndex);   // 0
            console.log(reg.exec(str));   // ["ab", index: 0, input: "ababab", groups: undefined]
            // 可以发现 reg.lastIndex 标示开始下一次匹配的字符位置,和 exec() 匹配结果中的 index 几乎一样
            // 而 reg.lastIndex 属性是可以修改的,我们修改一下试试
            console.log('-----------------------');
            reg.lastIndex = 4;
            console.log(reg.lastIndex);
            console.log(reg.exec(str));   // 可以发现 reg.lastIndex 的修改会影响 exec 的匹配结果,exec会从reg.lastIndex处开始匹配

            // 如果我们修改一个不刚好匹配的值呢
            console.log('+++++++++++++++++++++++++');
            reg.lastIndex = 1;
            console.log(reg.lastIndex);  // 1
            console.log(reg.exec(str));  // ["ab", index: 2, input: "ababab", groups: undefined]
            console.log(reg.lastIndex);  // 4
            console.log(reg.exec(str));  // ["ab", index: 4, input: "ababab", groups: undefined]
            // reg.lastIndex 会根据 exec 的匹配结果进行修正
            
        {
            let str = "aabbccaadd";
            let reg = /(\w)\1(\w)\2/g;
            console.log(reg.exec(str));   // ["aabb", "a", "b", index: 0, input: "aabbccaadd", groups: undefined]
            // aabb就是匹配到的字符串, 'a' 'b' 就是子表达式, index解释过,input就是str
        }
      非全局匹配:匹配的永远是第一个,且修改lastIndex无效
      {
            let str = "abc";
            let reg = /\w/;
            console.log(reg.exec(str));
            console.log(reg.exec(str));
            reg.lastIndex = 2;
            console.log(reg.exec(str));
        }

支持正则表达式的 String 对象的方法

  1. match
区别:
             match
                - 加 g ,返回一个类数组,数组中的每一项是匹配的值
                - 不加 g,匹配的和 exec 一置,永远返回第一个匹配的结果,且修改reg.lastIndex不会对其匹配照成影响
             exec
                - 加 g,执行一次匹配一次,与lastIndex相互影响
                - 不加 g,和match一致
  1. split
  2. replace
        {
            let str = 'jsplusplus';
            let res = str.replace('plus', '+');   // replace(regexp/substr,replacement)   param1: 被替换的, param2:替换后的
            console.log(res);  // js+plus      replace并没用全局匹配的能力  相当于  str.replace(/plus/, '+');
        }

        {
            let str = "aabbccdd";  // 替换为 bbaaddcc
            let reg = /(\w)\1(\w)\2/g;
            let res = str.replace(reg, '$2$2$1$1');  // $1就是子表达式\1的那个值, 这里的reg匹配到str有 aabb  ccdd 将aabb替换为bbaa,  ccdd替换为ddcc
            console.log(res);

            // 方式二
            str.replace(reg, ($, $1, $2) => {
                console.log($, $1, $2);    // aabb a b   ccdd c d  $:匹配的字符串 $1,$2:子表达式的值
                return $2 + $2 + $1 + $1;
            });
        }

        {
            // 练习
            let str = "js-plus-plus";  // 变为 jsPlusPlus
            let reg = /-(\w)/g;            // 这里的$1匹配的是子表达式,必须要加()
            let res = str.replace(reg, ($, $1) => {
                return $1.toUpperCase();
            });
            console.log(res);
        }

        {
            // 练习
            let str = "jsPlusPlus";  // 变为 js-plus-plus
            let reg = /(P)/g;
            let res = str.replace(reg, ($, $1) => {
                return '-' +$1.toLowerCase();
            });
            console.log(res);
        }

        {
            // 练习  xxyyzz => XxYyZz
            let str = "xxyyzz";
            let reg = /(\w)\1/g;
            let res = str.replace(reg, ($, $1) => {
                return $1.toUpperCase() + $1;
            });
            console.log(res);
        }

        {
            // 练习  aabbcc => a$b$c$,不使用function方式
            let str = "aabbcc";
            let reg = /(\w)\1(\w)\2(\w)\3/g;
            let res = str.replace(reg, '$1$$$2$$$3$$');   // 要使用$,必须写两个$,因为$有特殊含义
            console.log(res);
        }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,110评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,443评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,474评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,881评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,902评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,698评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,418评论 3 419
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,332评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,796评论 1 316
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,968评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,110评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,792评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,455评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,003评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,130评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,348评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,047评论 2 355