美文网首页Web前端之路让前端飞Web 前端开发
Javascript中的正则表达式——初识正则

Javascript中的正则表达式——初识正则

作者: ac68882199a1 | 来源:发表于2017-10-14 19:32 被阅读42次

    今天的这篇是补更的上周的内容,对于几乎迟到了整整一周的这件事,我感到很惭愧,因为自己没能很好的平衡工作和个人事务之间的关系。废话不多说,下面进入正题

    很多语言中都有对正则表达式的支持,javascript 也不例外。虽然我们经常听说正则,但是实际使用中却很少回去使用,原因无他——不会。所以今天我们就一起来认识一下正则表达式

    什么是正则表达式(Regular Expression)?
    使用单个字符串来描述、匹配某种规则的字符串

    正则表达式

    正则表达式由两种基本字符类型组成:原意文本字符和元字符

    元字符是在正则表达式中含有特殊含义的非字母字符,如:

    . * + ? $ ^ | \ ( ) { } [ ]
    

    当然,元字符并不止上面这些,还有 \t \b 等等

    字符类

    在正则中的一个字符对应着字符串中的一个字符,如:

    ab\t
    => ab // 最后一个为 tab 水平制表符
    

    但是往往我们需要表示的并不只是单独的一个字符,而可能是一类具有某种特征的字符,这时可以通过构建一个字符类来达到目的

    [abc] // [abc] 为一个整体,只对应字符串中的一个字符
    => a 
    => b
    => c
    

    上面的例子就通过构建了一个 [abc]字符类达到了匹配 abc 的目的

    如果要不匹配某一类字符的话,可以在中括号内的最前面添加 ^ 来达到取反的目的

    [^abc] // 不匹配 a 或 b 或 c
    

    范围类

    如果我们需要匹配一个数字,使用字符类可能会这样写 [0123456789] ,但是通过范围类可以达到很简单的书写方式

    [0-9] // 匹配数字
    [a-z] // 匹配小写英文字母
    [a-zA-Z] // 匹配所有英文字母
    

    范围类本身是一个闭区间,包括了范围的两头;同时也可以通过连写达到其他的匹配目的

    但是-本身并不是特殊字符,只有在两个文本字符之间时才能有表示范围的作用。那如果我们需要匹配-该怎么办呢?

    [0-9-] // 在最后加上 - ,从而达到匹配 0123456789- 的目的
    

    预定义类

    对于常用的范围类,正则为我们提供了一些同样作用的预定义类,如 [0-9] 等价于 \d ,常用的有以下这些:

    . => [^\r\n] // 除回车和换行符之外的所有字符
    \d => [0-9] // 所有数字
    \D => [^0-9] // 所有非数字
    \s => [\t\nx0B\f\r] // 空白符
    \S => [^\t\nx0B\f\r] // 非空白符
    \w => [a-zA-Z_0-9] // 单词字符(字母数字下划线)
    \W => [^a-zA-Z_0-9] // 非单词字符
    

    边界匹配

    ^ // 以xxx开始 (在中括号中表示取反)
    $ // 以xxx结束
    \b // 单词边界
    \B // 非单词边界
    

    举例说明:

    ^ac\d
    // 匹配以 a 开头,第二个字符为 c,第三个字符为数字的字符串,如 ac0 ac1r ac2fds 的前3个字符将会被匹配
    // bc0d ba13fsd b0adas 等将不会被匹配
    
    \di9$
    // 匹配以 9 结尾,倒数第二个字符为 i,倒数第三个字符为数字的字符串,如 das0i9 12i9 r324i9 的最后3个字符将会被匹配
    
    \bf\dk\b
    // 只匹配以 f 开头 k 结尾 中间是数字的三位字符串 f0k f1k f2k
    // af1k f1k3 f9i 等将不会被匹配
    
    \bf\dk\B
    // 只匹配以 f 开头,中间是数字,第三位是 k 且 k 不是结尾的字符串 f0k1 f0kkk f2k22
    // f0k f1k f2k fkk fkf fkk0 等将不会被匹配
    

    量词

    如果需要匹配一个十位数字,可能会这样写

    \d\d\d\d\d\d\d\d\d\d
    

    但也可以像下面这样写

    \d{10}
    

    {10} 就是一个量词描述

    量词有下面这些

    ? // 最多出现一次 a?
    + // 最少出现一次 a+
    * // 出现任意次 a*
    {n} // 出现 n 次 a{3}
    {n,m} // 出现 n 到 m 次 a{1,3}
    {n,} // 至少出现 n 次 a{2,}
    // 不存在 {,m} 的写法,它等同于 {0,m}
    

    贪婪模式与非贪婪模式

    如果有字符串12345678,有正则\d{3,6},那么它会如何匹配呢?

    正则在匹配的时候回尽可能多的匹配,所以上面的这个正则只会匹配到12345678将不会被匹配,这叫正则表达式的贪婪模式

    如果我们想要正则只要匹配到就不在继续匹配,就要使用正则的非贪婪模式,只需要在两次的后面加上?就可以了

    // 非贪婪模式的正则
    \d{3,6}?
    
    // 0123456789 这个字符串将会被匹配到 012 345 678
    

    分组

    当有一个单子需要被重复5次时,我们会这样写word{5},但是这个正则对应的字符串应该是worddddd,量词只会将它紧邻的字符重复

    所以如果要重复一个整体,就需要将word作为一个整体:

    (word){5}
    // wordwordwordwordword
    

    通过()我们可以达到分组的目的

    再举例:单词+数字连续重复3次

    ([a-zA-Z]\d){3}
    // a3f4d2
    // j9k0l8
    

    需要表示 word 或 number 这两个英文单词时,可以通过|来表示

    (word)|(number)
    // word
    // number
    // 需要注意的是不能写成 word|number 否则会匹配 wordumber 或者 wornumber
    

    反向引用

    当我们匹配一个字符串时,可能会需要获取原字符串中的内容,此时我们可以这样做

    // 原字符串
    2017-10-14
    
    // 正则
    (\d{4})-(\d{2})-(\d{2})
    
    // 需要转换成 10/14/2017 的格式,反向引用的表达式
    $2/$3/$1
    

    在正则中被分组的字符,我们可以按顺序通过 $1 $2 $3 ... 来捕获,如果需要引用原字符串的内容,只需要引用对应的 $1 $2 $3 ... 即可

    如果分组后不想捕获,可以忽略分组,只需要在分组内加上?:即可

    (\d{4})-(?:\d{2})-(\d{2})
    
    // 中间的第二个分组将会被忽略,原先的 $2 现在会获取到原先 $3 对应的值
    

    前瞻后顾

    正则在匹配到规则的时候,向前检查是否符合断言叫前瞻,向后检查则叫后顾

    文本的尾部为前,头部为后

    其中 js 不支持后顾

    符合肯定断言叫正向匹配,不符合叫负向匹配

    // assert 为断言正则
    
    // 正向前瞻
    exp(?=assert)
    //负向前瞻
    exp(?!assert)
    
    //正向后顾
    exp(?<=assert)
    
    //负向后顾
    exp(?<!assert)
    

    前瞻后顾不会被匹配,它只是作为是否匹配成功的一个条件

    \w(?=\d)
    // 匹配一个单词字符,如果这个字符后面是一个数字,则这个字符匹配成功,否则失败
    // a1 匹配到 a
    // _0 匹配到 _
    // a2b3 匹配到 a b
    // *0 由于第一个字符不是单词字符,匹配失败
    // aa 由于第二个字符不是数字,匹配失败
    

    正则表达式的学习可以有厚厚的一本书,如果想要深入学习正则的话,本篇文章的这点内容肯定是不够的
    但是作为提升我们平时开发效率的工具而言,掌握住上面这些也基本够用了
    下一篇(明天)我们来一起学习在 javascript 中如何使用正则表达式

    扫码关注前端周记公众号

    相关文章

      网友评论

        本文标题:Javascript中的正则表达式——初识正则

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