1. 正则表达式是国际标准,跨越语言;

  2. 正则表达式是一个规则,用于验证字符串;

使用场景

  1. 数据验证:可以测试输入字符串,以查看字符串内是否出现电话号码模式或信用卡号码模式;

  2. 替换文本:可以使用正则表达式来识别文档中的特定文本,完全删除该文本或者用其他文本替换它;

  3. 从字符串中提取子字符串:可以查找文档内或输入域内特定的文本;

元字符、修饰符

量词元字符

字符 描述
* 0 到多次,* 是贪婪的,会尽可能多的匹配文字,在它后面加上一个 ? 就可以实现非贪婪或最小匹配
+ 1 到多次,+ 是贪婪的,会尽可能多的匹配文字,在它后面加上一个 ? 就可以实现非贪婪或最小匹配
? 0 或 1 次
{ n } 出现 n 次 (n 为 0 或正整数)
{ n, } 出现 n 到多次 (n 为 0 或正整数)
{ n, m } 出现 n-m 次 (n 为 0 或正整数)

字符类

字符 描述
[ ] 匹配括号内的任意一个字符
/[abc]/g 匹配所有的字符 “a”、“b”、“c”, /[0-9]/g 匹配所有 0-9 中的数字
[^ ] 匹配除了括号内的字符以外的任意一个字符
/[^abc]/g 匹配除了字符 “a”、“b”、“c” 以外的所有任意字符

匹配特定类型的字符

字符 描述
\d 匹配一个数字字符,等价于 /[0-9]/
\D 匹配一个非数字字符,等价于 /[^0-9]/
\w 匹配字母、数字、下划线,等价于 /[A-Za-z0-9_]/
\W 匹配非字母、数字、下划线,等价于 /[^A-Za-z0-9_]/

特殊字符

字符 描述
\ 转义字符,用于匹配特殊字符本身
. 匹配除换行符 (\n、\r) 之外的任何单个字符,相等于 /[^\n\r]/
| 用于指定多个模式的选择

非打印字符

字符 描述
\n 匹配一个换行符
\r 匹配一个回车符
\s 匹配任何空白字符,包括空格、制表符、换页符等等
\S 匹配任何非空白字符
\t 匹配一个制表符

边界匹配

字符 描述
^ 匹配字符串的开头 (精确匹配)
$ 匹配字符串的结尾 (精确匹配)
\b 匹配单词边界,它匹配一个 单词的开始单词的结束 的位置,而不匹配任何实际的字符
\bword\b 匹配整个单词 “word”,但不匹配 “words” 或 “sword”
\B 匹配非单词边界,即匹配 单词的内部非单词的开头或结尾
\Bword\B 匹配 “swords” 中的 “word”,但不匹配 “word”、“sword”、 “words”

分组和捕获

概念说明

  1. 零宽:只匹配位置,零宽意味着断言在匹配时不会"消耗"字符串,它只是对位置进行条件判断,不包括匹配位置之前或之后的字符在匹配结果中;
  2. 先行:表示断言发生在匹配位置之前;
  3. 后行:表示断言发生在匹配位置之后;
  4. 正向:匹配括号中的表达式,即断言所作的条件判断是肯定的,即只有当条件成立时,匹配才成功;
  5. 负向:不匹配括号中的表达式,即断言所作的条件判断是否定的,即只有当条件不成立时,匹配才成功;
字符 描述
( ) 用于分组和捕获子表达式,它会把匹配到的内容保存到内存中,开发者可以使用 $n 来代表第 n( ) 中匹配到的内容
(?:pattern) 用于分组但不捕获子表达式,它匹配的内容不会被保存,所以无法使用 $n 获取
(?=pattern) 零宽正向先行断言,exp1(?=exp2) 匹配后面是 exp2exp1,匹配结果中不包含 exp2
(?!pattern) 零宽负向先行断言,exp1(?!exp2) 匹配后面不是 exp2exp1,匹配结果中不包含 exp2
(?<=pattern) 零宽正向后行断言,(?<=exp2)exp1 匹配前面是 exp2exp1,匹配结果中不包含 exp2
(?<!pattern) 零宽负向后行断言,(?<!exp2)exp1 匹配前面不是 exp2exp1,匹配结果中不包含 exp2

修饰符

字符 描述
i 不区分大小写,将匹配设置为不区分大小写,搜索时不区分大小写
m 多行匹配,使边界字符 ^$ 匹配每一行的开头和结尾,而不是整个字符串的开头和结尾
g 全局匹配,查找所有的匹配项

剖析

元字符

  1. ^ :以哪一个元字符作为开始

    // 必须以数字开始
    let reg = /^\d/;
    
    reg.test('2020baidu'); // true
    reg.test('baidu2020'); // false
    
  2. $ :以哪一个元字符作为结束

    // 必须以数字结束
    let reg = /\d$/;
    
    reg.test('2020baidu'); // false
    reg.test('baidu2020'); // true
    
    // ^ $都不加:字符串中包含符合规则的内容就可以
    let reg = /\d/;
    // ^ $都加:字符串只能是和规则一致的内容
    let reg = /^\d$/;
    
  3. \ :转义字符(普通->特殊->普通)

    // .不是小数点,是除了\n外的任意字符
    let reg = /^2.3$/;
    reg.test("2.3"); //=>true
    reg.test("2@3"); //=>true
    reg.test("23");  //=>true
    
    // 基于转义字符,让其只能代表小数点
    reg = /^2\.3$/;
    reg.test("2.3"); //=>true
    reg.test("2@3"); //=>false
    reg.test("23");  //=>false
    
    // \把特殊符号转换为普通的符号,\d原本代表 0-9 的数字,现在是字符串 \d
    reg = /^\\d$/;
    reg.test('\d'); //=>false
    reg.test('\\d');  //=>true,
    
  4. x | y :x 或者 y 中的一个字符

    let reg = /^18|29$/; // 18 开始或者 29 结尾的
    reg.test('18');   //=>true
    reg.test('129');  //=>true
    reg.test('189');  //=>true
    reg.test('1829'); //=>true
    reg.test('829');  //=>true
    reg.test('182');  //=>true
    reg.test('19');   //=>false
    
    // 直接 x|y 会存在很多优先级问题,一般都使用 () 进行分组,()会改变处理的优先级
    reg = /^(18|29)$/;// 18 或者 29
    reg.test("18");   // true
    reg.test("29");   // true
    reg.test("129");  // false
    reg.test("189");  // false
    reg.test("1829"); // false
    reg.test("829");  // false
    reg.test("182");  // false
    
  5. []:

    JavaScript
    JavaScript
    // [xyz]:x 或者 y 或者 z 中的一个字符
    let reg = /^[@+]$/;
    reg.test("@");  //=>true
    reg.test("+");  //=>true
    reg.test("++"); //=>false
    
    // [] 中不存在多位数
    let reg = /^[18]$/;
    reg.test("1");  //=>true
    reg.test("8");  //=>true
    reg.test("18"); //=>false
    
    //=> 1 或 3-6之间的数 或 9
    reg = /^[13-69]$/;
    reg.test("1");  //=>true
    reg.test("9");  //=>true
    reg.test("4");  //=>true
    reg.test("0");  //=>false
    reg.test("2");  //=>false
    

反向引用

  1. 反向引用:捕获组捕获到的内容在正则表达式内部进行引用,则为反向引用;

  2. 利用 \捕获组编号 反向引用之前的 捕获组

    // 找出该字符串中连续的字符
    var s = "aaaabbbbdefgg";
    var reg = /(\w)\1+/g;
    
    while (result = reg.exec(s)) {
        console.log(result);
    }
    
    // [ 'aaaa', 'a', index: 0, input: 'aaaabbbbdefgg', groups: undefined ]
    // [ 'bbbb', 'b', index: 4, input: 'aaaabbbbdefgg', groups: undefined ]
    // [ 'gg', 'g', index: 11, input: 'aaaabbbbdefgg', groups: undefined ]
    

捕获组

  1. 普通捕获组

    // 得到每个日期的 年、月、日
    var s = "2015-5-1, 2019-6-19";
    var reg = /(\d{4})-(\d{1,2})-(\d{1,2})/g;
    while ((result = reg.exec(s))) {
        console.log(result);
    }
    
    // [ '2015-5-1', '2015', '5', '1', index: 0, input: '2015-5-1, 2019-6-19', groups: undefined ]
    // [ '2019-6-19', '2019', '6', '19', index: 10, input: '2015-5-1, 2019-6-19', groups: undefined ]
    
  2. 具名捕获组 (?<命名>pattern):捕获组可以命名,最后都放入结果的 groups

    // 得到每个日期的 年、月、日
    var s = "2015-5-1, 2019-6-19";
    var reg = /(?<year>\d{4})-(?<month>\d{1,2})-(?<day>\d{1,2})/g;
    while (result = reg.exec(s)) {
        console.log(result);
    }
    
    // [ '2015-5-1', '2015', '5', '1', index: 0, input: '2015-5-1, 2019-6-19', groups: { year: '2015', month: '5', day: '1' } ]
    // [ '2019-6-19', '2019', '6', '19', index: 10, input: '2015-5-1, 2019-6-19', groups: { year: '2019', month: '6', day: '19' } ]
    

正向预查、负向预查

  1. 零宽正向先行断言,exp1(?=exp2) 匹配后面是 exp2exp1,匹配结果中不包含 exp2

    var s = "ricepudding.cn";
    var reg = /ricepudding(?=\.cn)/g;
    while ((result = reg.exec(s))) {
        console.log(result);
    }
    
    // [ 'ricepudding', index: 0, input: 'ricepudding.cn', groups: undefined ]
    
  2. 零宽负向先行断言,exp1(?!exp2) 匹配后面不是 exp2exp1,匹配结果中不包含 exp2

    var s = "ricepudding.1cn";
    var reg = /ricepudding(?!\.cn)/g;
    while ((result = reg.exec(s))) {
        console.log(result);
    }
    
    // [ 'ricepudding', index: 0, input: 'ricepudding.1cn', groups: undefined ]
    
  3. 零宽正向后行断言,(?<=exp2)exp1 匹配前面是 exp2exp1,匹配结果中不包含 exp2

    var s = "ricepudding.cn";
    var reg = /(?<=ricepudding)\.cn/g;
    while ((result = reg.exec(s))) {
        console.log(result);
    }
    // [ '.cn', index: 11, input: 'ricepudding.cn', groups: undefined ]
    
  4. 零宽负向后行断言,(?<!exp2)exp1 匹配前面不是 exp2exp1,匹配结果中不包含 exp2

    var s = "ricepudding1.cn";
    var reg = /(?<!ricepudding)\.cn/g;
    while ((result = reg.exec(s))) {
        console.log(result);
    }
    // [ '.cn', index: 12, input: 'ricepudding1.cn', groups: undefined ]
    

在线工具

  1. 正则表达式在线测试

  2. 正则表达式可视化图解

打赏作者
您的打赏是我前进的动力
微信
支付宝
评论

中午好👏🏻,我是 ✍🏻   疯狂 codding 中...

粽子

这有关于前端开发的技术文档和你分享。

相信你可以在这里找到对你有用的知识和教程。

了解更多

目录

  1. 1. 使用场景
  2. 2. 元字符、修饰符
    1. 2.1. 量词元字符
    2. 2.2. 字符类
    3. 2.3. 匹配特定类型的字符
    4. 2.4. 特殊字符
    5. 2.5. 非打印字符
    6. 2.6. 边界匹配
    7. 2.7. 分组和捕获
    8. 2.8. 修饰符
  3. 3. 剖析
    1. 3.1. 元字符
    2. 3.2. 反向引用
    3. 3.3. 捕获组
    4. 3.4. 正向预查、负向预查
  4. 4. 在线工具