• JS 正则 方案
  • 基本字符
    • 会精确匹配一段字符,如hi。这段字符可以出现多次
  • 字面量
    • /^[a-z]+$/.text(str); # ^代表开头, $是结尾
  • 转义
    • \
  • 元字符 # metacharacter
    • .
      • 匹配除换行符以外任意字符
    • \b
      • 表示单词的开头或结尾,也就是单词的分界。只匹配一个位置\s\S
      • \bhi\b
        • hi单词
    • \d
      • 表示数字
    • \s
      • 匹配任意空白符,包括空格、tab、换行、中文全角空格等
      • \s\S
        • 匹配包括\n在内的所有字符
    • \w
      • 匹配非特殊字符,包括字母、数字、下划线或汉字
    • ^
      • 匹配开头
    • $
      • 匹配结尾
    • 反义
      • \W
        • 非字符
      • \S
        • 非空白
      • \D
        • 非数字c
      • \B
        • 非单词位置
    • [^x]
      • 非x, [^aeiou] 除了aeiou以外的任意字符
  • 限定字符
    • {2}
      • 表示前面的内容出现2次, {5, 12}内容出现5到12次, {5, }内容出现5或更多次
    • ?
      • 零次或一次
        • 零个或多个
        • 表示一个或多个
  • 字符类
    • [aeiou]
      • 匹配其中的一个, [.?!] 匹配.或?或!
    • [0-9]
      • 同\d, [a-z0-9A-Z] 同\w
  • 分枝条件
    • | # jpg|png,
      • 每个分支都从第一个分支开始匹配, 如\d{5}|\d{5}-d{4}只能匹配11111或11111-2222中的11111
  • 分组 # 零宽断言只占用不消费
    • ()
    • 语法
      • (exp)
      • (?exp) # 组命名
      • (?:exp) # 消费exp, 不捕获匹配的文本,也不分配组号
      • (?=exp) # 零宽断言,正向前瞻,后面能匹配表达式exp
        • \b\w+(?=ing\b) # 匹配以ing结尾单词的前面部分,如dancing中的danc
        • /(\w)\1{2}(?=(\w)\2{2})/g # 匹配所有在3个连续相同字符前的相邻3个连续相同字符, aaalllsss0tAAAnnn999结果是aaa, lll, AAA, nnn
      • (?exp) # 零宽断言,正向后瞻,前面能匹配表达式exp
        • (?\bre)\w+\b # 匹配以re开头单词的后半部分,如reading中的ading
      • (?!exp) # 零宽断言,负向前瞻,后面不匹配exp的位置, js不支持
        • \b\wq(?!u)\w\b # 匹配一个单词,该单词包含后面不是字母u的字母q
        • \d{3}(?!\d) # 匹配三位数字,且它们后面不能有数字
        • \b((?!abc)\w)+\b # 匹配不包含连续字符串abc的单词
      • (?<!exp) # 零宽断言,负向后瞻,前面不匹配exp的位置, js不支持
        • (?<![a-z])\d{7} # 匹配前面不是小写字母的七位数字
      • (?#comment) # 注释
  • 后向引用 # 分组捕获后会自动编号,从左到右,1234。后向引用用于引用前面匹配到的文本,如 \1 代表分组1匹配的文本
    • \b(\w+)\b\s+\1\b # 匹配重复的单词, 如go go
    • (?\w+) 或 (?’Word’\w+) # 把\w+的组名指定为Word, 用\k引用
  • 贪婪与懒惰
    • 包含能接受重复限定符时,会匹配尽可能多的字符。如a.*b
    • a.*?b会懒惰匹配
      • 懒惰限定符
        • ? 重复懒惰匹配任意次
        • +? 重复懒惰匹配1次或多次
        • ?? 重复懒惰匹配0次或1次
        • {n, m}? 重复懒惰匹配n到m次
        • {n,}? 重复懒惰匹配n次以上
  • 平衡组/递归匹配
    • (?‘group’) 把捕获的内容命名为group,并压入栈(Stack)
    • (?’-group’) 从栈中弹出最后压入的名为group的捕获内容。如果栈为空,则匹配失效
    • (?(group)yes|no) 如果栈中存在名为group的捕获内容,继续匹配yes部分的表达式,否则则继续匹配no部分的表达式
    • 示例 # 平衡组最常见的应用是匹配HTML
      • 匹配xx<aaaa>yy
        • 思路
          • 每碰到左括号,就压入一个Open, 每碰到右括号,弹出一个
          • 最后看栈是否空,如果否则表示不配对,应该失败
          • 正则表达式引擎会进行回溯(放弃最前面或最后面一些字符), 尽量使整个表达式得到匹配
      • < # 最外层的左括号 - [^<>]* # 后面非括号的内容
      • (
      • (
      • (?’Open’<) # 又碰到了左括号, 压入一个Open
      • [^<>]* # 后面非括号内容
      • )+
      • (
      • (?’-Open’>) # 碰到了右括号, 擦掉一个Open
      • [^<>]* # 后面非括号内容
      • )+
      • )*
      • (?(Open)(?!)) # 负向前瞻,判断栈中还有没有Open, 有则匹配失败
      • > # 最外层右括号
      • )
  • 特点
    • js中不支持 回顾后发断言
    • 可以跟三个flag,比如/something/igm
      • i表示不区分大小写
      • g表示匹配多个
        • g会影响String.prototype.match()和RegExp.prototype.exec()的行为
        • match中加g会返回数组,不加g返回比较详细的信息
        • exec中加g,且正则存在变量中时,该正则变量执行exec后会存储信息, 如
        • var re = /h(.*?)\b/g;
        • re.exec(‘hello helloo’) 执行三次,匹配内容有变化
      • m表示,^$可以匹配每一个的开头和结尾
    • api
      • RegExp
        • exec # 执行第一个, exp本身保留执行状态
          • exp = /#/
            exp.exec('##')
        • test
      • String
        • replace # 替换第一个, ‘abc - 123 - #$*’
          • 'John Smith'.replace(/(\w+)\s(\w+)/, '$2, $1')
            'abc123#$*'.replace(/([^\d]*)(\d*)([^\w]*)/, function replacer(match, p1, p2, p3, offset, string) {
            return [p1, p2, p3].join(' - ');
            });
        • replaceAll
        • match # 不能有g选项,只得到第一个匹配
    • .net中处理选项
      • IgnoreCase
        • 忽略大小写
      • Multiline
        • 多行模式, 更改^$的含义为一行首和行尾, $表示\n之前的位置以及字符串结束前的位置
      • Singleline
        • 单行模式(可以与Multiline通用),更改.的含义,便它与每一个字符匹配(包括\n)
      • IgnorePatternWhitespace
        • 忽略空白,会忽略表达式中非转义空白并启用#作为标记注释
      • ExplicitCapture
        • 显式捕获,仅捕获已被显式命名的组
  • 元字符扩展
    • \a # 报警字符
    • \t # 制表符
    • \v # 竖向制表符
    • \r # 回车
    • \f # 换页符
    • \n # 换行符
    • \e # Escape
    • \0nn # ASCII码中八进制代码为nn的字符
    • \xnn # ASCII码中十六进制代码为nn的字符
    • \unnnn # Unicode码中十六进制代码为nnnn的字符
    • \cN # ASCII控制字符,如\cC 代表ctrl + c
    • \A # 字符串开头,同^但不受多行选项影响
    • \Z # 字符串结尾或行尾,不受多行选项影响
    • \z # 字符串结尾,同$但不受多行选项影响
    • \G # 当前搜索的开头
    • \p{name} # Unicode中命名为name的字符类,如\p{IsGreek}
    • (?>exp) # 贪婪子表达式
    • (?-exp) # 平衡组
    • (?im-nsx:exp) # 在子表达式exp中改变处理选项
    • (?im-nsx) # 为表达式后面的部分改变处理选项
    • (?(exp)yes|no) # 把exp当作零宽正向先行断言,如果能匹配,使用yes作为此组表达式,否则使用no
      • (?(exp)yes) 只使用空表达式为no
      • (?(name)yes|no) 命名为name的组捕获到内容,使用yes