正则表达式学习

测试工具

JavaScript 中的用法

  • replace方法: stringObject.replace(regexp,replacement)

    • replacement 参数
      • $1、$2、...、$99: 与 regexp 中的第 1 到第 99 个子表达式相匹配的文本
      • $&: 与 regexp 相匹配的子串。
      • $`: 位于匹配子串左侧的文本。
      • $': 位于匹配子串右侧的文本。
      • %: 直接量符号。
    • 例子

      1
      2
      3
      // 替换两个名字的顺序
      name = "Doe, John";
      name.replace(/(\w+)\s*, \s*(\w+)/, "$2 $1");

RegExp 对象

  • 修饰符
    • i: 执行对大小写不敏感的匹配 => /[a-z]/i 匹配a-z,A-Z
    • g: 执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)=> /[a-z]/g
    • m: 执行多行匹配

普通语法

  • 例子

    • 0\d{2}-\d{8} 匹配 010-88888888 这类的电话
    • ^\d{5,12}$ 填写的 QQ 号必须为 5 位到 12 位数字时
    • \ba\w*\b 匹配以字母 a 开头的单词
    • \(?0\d{2}[) -]?\d{8} 匹配几种格式的电话:
      (010)88886666,或 022-22334455,或 02912345678
    • ((2([0-4]\d|5[0-5])|1?\d{1,2})\.){3}(2([0-4]\d|5[0-5])|1?\d{1,2}) 匹配 IP 地址
    • \b(\w+)\b\s+\1\b 可以用来匹配重复的单词,像 go go, 或者 kitty kitty
    • \b(?<Word>\w+)\b\s+\k<Word>\b 也可以
    • url 解析 的例子:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      function parseUrl(url){
      var urlPattern = /^(?:([A-Za-z]+):)?(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/;
      var result = urlPattern.exec(url);
      var type = ['url', 'scheme', 'slash', 'host', 'port', 'path', 'query', 'hash'];

      return result;
      }

      parseUrl("http://tool.oschina.net:80/regex?haha=true#fragment");
      // ["http://tool.oschina.net:80/regex?haha=true#fragment", "http", "//", "tool.oschina.net", "80", "regex", "haha=true", "fragment"]
  • 元字符

    • \w 匹配 字符、数字、下划线、汉字 等
    • \d 匹配数字
    • \s 匹配任意的空白符:空格,制表,换行,中文全角空格等
    • . 匹配除换行符(结束符)以外的任意字符
  • 位置匹配:

    • ^:”字符串”的开始
    • $:”字符串”的结束
    • \b: 表示一个位置 => 其前一个和后一个字符不全是 \w
  • 重复匹配:限定符

    • * 重复零次或更多次
    • + 重复一次或更多次
    • ? 重复零次或一次
    • {n} 重复n次
    • {n,} 重复n次或更多次
    • {n,m} 重复n到m次
  • 元素集:[] 里面表示一个范围

    • [aeiou] 匹配英文元音字母
    • [0-9] 匹配数字,即\d
    • [0-9a-zA-Z] 匹配数字和字母
  • 分支条件:| 把几种不同的规则分隔开(按顺序匹配)

    • 0\d{2}-\d{8}|0\d{3}-\d{7} 这个表达式能匹配两种以连字号分隔的电话号码:一种是三位区号,8 位本地号(010-12345678),一种是4位区号,7位本地号(0376-2233445)。
  • 分组:可以用小括号来指定子表达式(也叫做分组)

    • (\d{1,3}\.){3}\d{1,3} 是一个简单的 IP 地址匹配表达式
  • 反义:

    • \W 匹配任意不是字母,数字,下划线,汉字的字符
    • \S 匹配任意不是空白符的字符
    • \D 匹配任意非数字的字符
    • \B 匹配不是单词开头或结束的位置
    • [^x] 匹配 除了 x 以外 的任意字符
    • [^aeiou] 匹配除了 aeiou 这几个字母以外的任意字符
  • 后向引用(分组):使用小括号指定一个子表达式后,匹配这个子表达式的文本(也就是此分组捕获的内容)可以在表达式或其它程序中作进一步的处理。默认情况下,每个分组会自动拥有一个组号,规则是: 从左向右,以分组的左括号为标志,第一个出现的分组的组号为1,第二个为2

    • \1: 代表分组1匹配的文本
    • 捕获
      • (exp) 匹配 exp,并捕获文本到自动命名的组里
      • (?<name>exp) 匹配 exp,并捕获文本到名称为 name 的组里,也可以写成 (?'name'exp)
      • (?:exp) 匹配 exp,不捕获匹配的文本,也不给此分组分配组号
  • 零宽断言(匹配位置!):用于查找在某些内容(但并不包括这些内容)之前或之后的东西,也就是说它们像\b,^,$那样用于指定一个位置,这个位置应该满足一定的条件(即断言),因此它们也被称为零宽断言

    • (?=exp) 零宽度正预测先行断言,断言自身出现的位置的后面能匹配表达式 exp,也就是匹配 exp 前面的位置
      • \b\w+(?=ing\b) 匹配以 ing 结尾的单词的前面部分(除了 ing 以外的部分)
    • (?<=exp) 零宽度正回顾后发断言,匹配 exp 后面的位置
    • (?!exp) 匹配后面跟的不是 exp 的位置
    • (?<!exp) 匹配前面不是 exp 的位置
  • 匹配优先级:

    • 最先开始的匹配拥有最高优先级 —— The match that begins earliest wins
    • 贪婪:当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符
    • 转化为懒惰匹配模式:要在限定符后面加上一个问号 ?
  • 需要转义的字符要注意

    • \/: 避免误认为是 正则表达式的结束符
    • \?: 避免误认为是 非捕获匹配符或是限定符
    • \.: 避免误认为是 任意匹配元字符
  • 练习:

    • 匹配数字: /^-?$/