正则表达式学习

276 阅读3分钟

1. 正则表达式的创建

1.1 使用字面量来创建正则表达式

let reg = /=\d+/g
reg = /\d+/

在两个 / 之间的字符通常为 元字符字面量字符

而在第二个 / 之后的字符则为 修饰符, 修饰符 可以没有

1.2 通过构造函数 RegExp 来创建正则表达式

let reg = new RegExp("\\d+", g)
reg = new RegExp("abc\\d+")

由于 \ 是转移字符, 所以要用 \\ 来表示 \

new RegExp 的时候, 第一个参数为 元字符 | 字面量字符, 第二个参数为 修饰符

2. 正则表达式的匹配规则

2.1. 字面量字符

大部分字符在正则表达式中, 匹配的就其本身, 如 /abc/ 匹配字符串 abc, /2000/ 匹配字符串 2000.

这样的字符在正则表达式中被称作 字面量字符

let reg = /a/ 
// 匹配字符 "a"
reg = /1/ 
// 匹配字符 "1"

2.2. 元字符

除了 字面量字符, 正则表达式更多使用的还是 元字符

元字符 通常都具有特殊的含义

2.2.1 量词类 ? , * , + , {}

  1. ? 表示上一个表达式出现 [0, 1] 次, 与 {0, 1} 同义
  2. * 表示上一个表达式出现 [0, +∞) 次, 与 {0,} 同义
  3. + 表示上一个表达式出现 [1, +∞) 次, 与 {1,} 同义
let reg = /abc?/
// 可以匹配 "abc", "ab". 不能匹配 "abd"
reg = /a*b/
// 可以匹配 "b", "ab", "aaaaab"
reg = /a+b/
// 可以匹配 "aaaabb", "ab". 不能匹配 "b"

2.2.2 位置匹配类 ^ , $

  1. ^ 表示匹配对应字符串的开始
  2. $ 表示匹配对应字符串的结尾
let reg = /^ha*o$/
// 可以匹配以 "h" 为头, 以 "o" 为尾, 中间出现 0 到 多个 "a" 的字符串
// 如 "haao" "ho" 就可以匹配到
// 但若是不以 "h" 为头 或 不以 "o" 为尾, 则无法匹配
// 如 "ahaao", "haaoa", "ahaaoa" 就不能匹配到

2.2.3 常用特殊匹配字符 . , \d , \w , \s , \b , []

  1. [] : 通常表示匹配 [] 中的某一个字符

    注意: 在 [] 中, 量词类位置匹配类 的字符没有特殊含义

    let reg = /[ab12]/
    // 匹配 "a", "b", "1", "2" 中的任意一个字符
    reg = /[ab+c*d?]/
    // 匹配 "a", "b", "+", "c", "*", "d", "?" 中的任意一个字符
    
  2. . : 通常用来匹配 除换行符 \n 以外的任意字符

    let reg = /.s/
    // 匹配 "this", 结果是 "is"; 匹配 "was", 结果是 "as"; 匹配 " s", 结果是 " s"; 不能匹配 "s"
    
  3. \d : 通常用来匹配 数字, 等价于 [0-9]

  4. \w : 通常用来匹配 数字|字母|下划线, 等价于 [0-9a-zA-z_]

  5. \s : 通常用来匹配 空白字符, 等价于 [ \f\n\r\t\v\u00a0\u1680\u180e\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]

  6. \b : 通常用来表示 单词的边界

    let reg = /\bword\b/g
    // 匹配 "word theword isaword word" 中第一个和最后一个单词 "word"
    

2.2.4 特殊的匹配规则 x(?=y) , (?<=y)x , x(?!y) , (?<!y)x

  1. x(?=y)

    先行断言 : 只有当符合 x 的表达式后面立即跟着一个符合表达式 y 的字符串的时候, 才能够匹配

    let reg = /name=(?=\w+)/
    // 可以匹配 "name=saber", 匹配结果是 "name=". 不能匹配 "name="
    
  2. (?<=y)x

    后行断言 : 只有当符合 x 的表达式前面跟着一个符合表达式 y 的字符串的时候, 才能够进行匹配

    let reg = /(?<=name=)\w+/
    // 可以匹配到 "name=saber" 中的 "saber". 无法匹配 "saber"
    
  3. x(?!y)

    正向否定查找 : 只有当符合 x 表达式后面跟着一个不符合表达式 y 的字符串的时候, 才能够匹配

    let reg = /name=(?!saber)/
    // 可以匹配到 "name=berserker" 中的 "name=". 无法匹配 "name=saber"
    
  4. (?<!y)x

    反向否定查找 : 只有当符合 x 表达式前面跟着一个不符合表达式 y 的字符串的时候, 才能够匹配

    let reg = /(?<!id=)saber/
    // 可以匹配到 "name=saber" 中的 "saber", 无法匹配到 "id=saber"
    

2.3 修饰符 g , i , m

  1. g 表示使用该正则表达式进行全局匹配, 在没有使用 g 时, 正则表达式通常只匹配一个结果

    let reg = /\dabc/
    // 匹配 "0abc1abc2abc3" 的结果为 "0abc"
    reg = /\dabc/g
    // 匹配 "0abc1abc2abc3" 的结果为 "0abc", "1abc", "2abc"
    
  2. i 表示使用该正则表达式时忽略字母大小写

  3. m 表示使用该正则表达式时可以跨行匹配

    m 修饰符可以对 ^ , $ 的语义进行修改:

    • 正则表达式 /^a.*b$/ 表示对以 a 开始, 以 b 结尾的整段字符串进行匹配

    • /^a.*b$/m/^a.*b$/ 的基础上添加了语义: 匹配整段字符串中第一行以 "a" 开始, 以 "b" 结尾的字符串

    let reg = /^a.*c$/m
    // 对 "abbc\nabdc" 进行匹配, 有 "abbc"
    reg = /^a[\w\s]*c$/m
    // 能完整对 "abbc\nabdc" 进行匹配(正则匹配的贪婪性?)
    reg = /^a[\w\s]*c$/
    // 无法匹配 "abc\nabd" (因为字符串并没有以 "c" 结尾), 可以匹配到整个字符串 "acccd\nbdcc"
    

2.4 分组捕获

  1. () 分组, 既可以将 () 内的内容看作一个表达式, 又可以对符合括号内表达式的结果进行捕获 (即能够获取到与该括号内的表达式所匹配的结果)

    let reg = /(\d+).(\d+)/
    let str = "0.0"
    str.match(reg) //=> ["0.0", "0", "0", index: 0, input: "0.0", groups: undefined]
    // 第 0 项是正则匹配的结果, 其余项(以数字为 key)是分组捕获的结果
    
  2. \number

    \1 表示该匹配的结果与第 1 个分组匹配的结果相同, \2 表示该匹配与第 2 个分组匹配的结果相同...

    let reg = /(\d+).(\d+)\1\2/
    let str = "123.234123234"
    str.match(reg) //=> ["123.234123234", "123", "234", index: 0, input: "123.234123234", groups: undefined]
    reg = /(\d+).(\d+)\1\1/
    str.match(reg) //=> ["23.23412323", "23", "2341", index: 1, input: "123.234123234", groups: undefined]
    
  3. (?:x)

    匹配但不捕获: 对括号内的表达式 x 所匹配的结果不进行捕获

    let reg = /(\d+).(?:\d+)/
    let str = "1.2"
    str.match(reg) //=> ["1.2", "1", index: 0, input: "1.2", groups: undefined]
    

2.5 正则匹配的贪婪性

贪婪性指的是: 每次匹配的结果尽可能长

let reg = /\d+/
// 对 "123s" 进行匹配, 匹配到的是 "123"
// 而不是 "1", "2", "3", "12", "23" 中的任意一个

取消正则的贪婪性: 在量词类字符后加上 ?, 则匹配满足最低条件的字符串即止

let reg = /\d+?/ 
// 表示匹配 1 个数字
reg = /\d*?/
// 表示 1 个数字都不匹配
let reg = /\d??/
// 表示 1 个数字都不匹配
reg = /\d{4,}?/ 
// 表示匹配 4 个数字