美文网首页
正则表达式

正则表达式

作者: Patrick浩 | 来源:发表于2018-05-20 21:19 被阅读0次
    正则表达式.png

    公司的小伙伴希望能讲一下正则表达式,于是趁着这个机会自己也把正则表达式的重新学习了一下,由于不同语言对正则表达式提供了不同的方法支持,以下所有的正则测试均基于Javascript

    1. 元字符

    正则表达式中的字符可以认为有两类,一类被称为元字符,代表的是有在正则表达式中有特殊含义的字符,另一类就是普通字符。
    个人认为元字符分为了三类:固有语义,简写字符集和分组匹配

    1.1 固有语义的字符

    1.1.1 选择字符

    选择字符有两种[][^][]表示匹配结果包含[]中的任意字符,[^]则表示匹配结果不能包含[^]中的字符

    /[1234]/.test('1'); // true
    /[1234]/.test('5'); // false
    /[^1234]/.test('2'); // false
    /[^1234]/.test('5'); // true
    

    需要注意的是[][^]中的字符,除开部分特殊字符外(例如:[,],-等),都是自带转义属性。也就是说[]中的字符都不再具有特殊意义

    // 在正则中‘.’是任意匹配的意思,但是[]中失去了其本来的意义
    /./.test(1); // true
    /[.]/.test(1);  // false
    /[.]/.test('.');  // true
    

    1.1.2 重复字符

    表示一个字符出现次数包括:?, *, +, {m, n}

    // 0次或1次匹配
    /[a]?/.test('a'); // true
    /[a]?/.test('b'); // true
    // 0次或多次匹配
    /[a]*/.test('a'); // true
    /[a]*/.test('b'); // true
    // 1次或多次匹配
    /[a]+/.test('a'); // true
    /[a]+/.test('b'); // false
    // 出现m到n次
    /[a]{2,3}/.test('aab'); // true
    /[a]{2,3}/.test('abab'); // false
    

    1.1.3 锚点字符

    有表示开始的^和表示结束的$,用于限制正则匹配的开始和结束

    /[1]/.test('12'); // true
    // 以1开头
    /^[1]/.test('21'); // false
    /^[1]/.test('12'); // true
    // 以1结尾
    /[1]$/.test('12'); // false
    /[1]$/.test('21'); // true
    

    1.1.4 转义字符

    使用\来进行将一些元字符进行转义,从而使得元字符可以进行匹配

    /[]/.test('[]'); // false
    /\[\]/.test('[]'); // true
    

    1.1.5 通配字符

    使用.来匹配任意字符,只要匹配字符串不为空匹配结果都为真

    /./.test('a-1sd'); // true    
    

    1.1.6 或字符

    使用|来对多个字符取并集匹配

    /1|2/.test('1'); // true, 等价于/[12]/.test('1')
    /1|2/.test('2'); // true, 等价于/[12]/.test('1')
    /The|to/.test('to'); // true
    

    1.1.7 非贪婪匹配

    在重复字符后面使用?来进行非贪婪匹配,非贪婪匹配是指在匹配字符对时候尽可能少的匹配

    // 使用replace函数来验证
    'aaab'.replace(/[a]+/g, '='); // =b
    'aaab'.replace(/[a]+?/g, '='); // ===b
    

    上面的例子中:
    第一个使用了贪婪模式,因此\[a]+\将匹配aaa,因此执行替换的时候将aaa替换为了=
    第二个使用了非贪婪匹配,因此\[a]+?\将分别匹配每个a,因此最后将每个a分别替换为=aaa就变为===

    1.2 简写字符集

    将一些字符,和转义符号配合使用,可以得到一些正则表达式默认匹配范围

    1.2.1 字符数字匹配集

    使用\w可以匹配字符数字,相当于[a-zA-Z0-9_],而\W匹配所有非字符数字,相当于[^a-zA-Z0-9_]

    /\w/.test('1'); // true
    /\W/.test('1'); // false
    

    1.2.2 数字匹配集

    使用\d匹配数字,相当于[0-9],同样\D匹配非数字,相当于[^0-9]

    /\d/.test('1'); // true
    /\D/.test('1'); // false
    

    1.2.3 空格匹配集

    使用\s匹配空格,相当于[ ],使用\S匹配非空格,相当于[^ ]

    /\s/.test(' '); // true
    /\S/.test(' '); // false
    

    1.2.4 其他

    其他还包括换行符匹配\n,回车匹配\r,制表符匹配\t

    1.3 分组

    正则表达式中可以将匹配进行分组,并可以分别获取匹配的分组,同时表达式中也可以指定分组的引用

    1.3.1 分组匹配

    使用()可以将正则表达式进行分组

    /(The)|(To)/.test('The'); // true
    

    看上去和之前的差不多,但是,这里可以在正则表达式中,利用捕获模式(/ + 数字)和替换模式($ + 数字)获取,获得对应分组的引用,分组的计数是从1开始的

    // 捕获模式
    /(The)(To)\1/.test('TheTo'); // false
    /(The)(To)\1/.test('TheToThe'); // true
    /(The|To)\1/.test('TheThe'); // true
    /(The|To)\1/.test('ToTo'); // true
    /(The|To)\1/.test('TheTo'); // false
    // 替换模式
    'TheTo'.replace(/(The)(To)/, '$2$1') // ToThe
    

    1.3.2 非获取匹配

    在分组匹配中,可以使用(?)的方式,来进行匹配,但是匹配后不进行存储使用,也就是不能使用捕获模式和替换模式的方式获取到分组信息

    1.3.2.1 匹配不获取

    使用(?:)去匹配字符,通常和|来组合使用

    /Test(?:er|or)/.test('Tester'); // true
    /Test(?:er|or)/.test('Testor'); // true
    /Test(er|or)\1/.test('Testerer'); // true
    /Test(er|or)\1/.test('Testoror'); // true
    /Test(?:er|or)\1/.test('Testeror'); // false
    /Test(?:er|or)\1/.test('Tester\1'); // true
    

    1.3.2.2 正向预查匹配

    使用(?=)来进行正向匹配,匹配字符串开始处进行查找

    /Windows(?=2000|3000)/.test('Windows3000'); // true
    /Windows(?=2000|3000)/.test('Windows4000'); // false
    

    1.3.2.3 正向预查不匹配

    使用(?!)来进行匹配和(?=)刚好相反

    /Windows(?!2000|3000)/.test('Windows3000'); // false
    /Windows(?!2000|3000)/.test('Windows4000'); // true
    

    1.3.2.4 反向预查匹配

    使用(?<=)来进行匹配

    /(?<=2000|3000)Windows/.test('3000Windows'); // true
    /(?<=2000|3000)Windows/.test('4000Windows'); // false
    

    1.3.2.4 反向预查不匹配

    使用(?<!)来进行匹配,和(?<=)相反

    /(?<!2000|3000)Windows/.test('3000Windows'); // false
    /(?<!2000|3000)Windows/.test('4000Windows'); // true
    

    2. 匹配模式

    常用的匹配模式有三个:i, g, m,不同的语言支持的匹配模式的会有所不同

    2.1 忽略大小匹配

    使用i做为匹配模式,可以忽略匹配中的大小写

    /[A]/.test('a'); // false
    /[A]/i.test('a'); // true
    

    2.2 全局匹配

    使用g做为匹配模式,可以匹配字符串中的所有字符,而不是第一个字符

    'abcabcabc'.replace(/[a]/, '='); // =bcabcabc
    'abcabcabc'.replace(/[a]/g, '='); // =bc=bc=bc
    

    2.2 多行匹配

    使用m做为匹配模式,可以匹配多行字符,通常和g一起使用

    3. Javascript支持正则的方法

    3.1 支持的方法

    各语言都提供了各种支持正则都方法,Javascript以下方法都支持正则表达式的使用:

    RegExp.prototype.exec()
    RegExp.prototype.test()
    String.prototype.replace()

    3.2 lastIndex

    Javascript中,在正则表达式对象存在lastIndex属性,每进行一次匹配,这个属性会进行更新为当前匹配位置,并以在下一次匹配时,以这个位置开始进行匹配

    let str = 'abc';
    let reg = /[a]/g;
    reg.test(str); // true
    console.log(reg.lastIndex); // 1
    reg.test(str); // false
    // 由于匹配失败,所以会被重置为0
    console.log(reg.lastIndex); // 0
    

    4. 总结

    正则表达式的识别主要是区别元符号和普通符号的,同时注意转义符号的使用特点,读懂正则表达式就不难了。

    5. 参考

    你应该学习正则表达式
    Learn-regex-easy-way
    百度百科-正则表达式
    MDN-RegExp

    相关文章

      网友评论

          本文标题:正则表达式

          本文链接:https://www.haomeiwen.com/subject/ucbvdftx.html