Skip to content

RegExp

[TOC]

索引

构造方法

  • new RegExp()(pattern, flags?),用于动态创建正则表达式对象的构造函数,适用于模式需要运行时拼接的场景。

方法

  • re.exec()(str),用于执行正则匹配并返回详细匹配信息
  • re.test()(str),用于快速检测字符串中是否存在匹配模式

RegExp

构造方法

new RegExp()@

new RegExp()(pattern, flags?),用于动态创建正则表达式对象的构造函数,适用于模式需要运行时拼接的场景。

  • patternstring,文本模式定义正则表达式的匹配规则。

  • flags?g|i|m|s|u|y,修饰符,控制正则表达式的匹配行为。

    • g:全局匹配。

    • i:忽略大小写。

    • m:多行匹配。

    • s:允许 . 匹配换行符。

    • u:使用 unicode 码的模式进行匹配。

    • y:执行“粘性 (sticky)”搜索,匹配从目标字符串的当前位置开始。

  • 返回:

  • reRegExp,返回包含模式和修饰符的正则表达式对象。

基本示例

  1. 基础用法

    js
    // 匹配所有数字(全局+忽略大小写)
    const regex = new RegExp("\\d", "gi");
    console.log("A1B2C3".match(regex)); // ["1", "2", "3"]

注意事项

  1. 转义规则:字符串中的 \ 需写为 \\,因为字符串本身会解释一次转义:

    js
    // 匹配数字 \d → 需写成 "\\d"
    const digitPattern = new RegExp("\\d+"); // 等价于 /\d+/
    
    // 匹配点号(.)→ 需写成 "\\."
    const dotPattern = new RegExp("\\."); // 等价于 /\./
  2. 性能考虑

    • 避免在循环中重复创建相同的 RegExp 对象(建议提前创建)。
    • 静态模式优先使用字面量 /.../(加载时编译,效率更高)。
  3. 标志覆盖:当第一个参数是正则对象时,提供 flags覆盖原标志:

    js
    const re = new RegExp(/abc/g, "i"); 
    console.log(re.flags); // "i"(覆盖了 g)
  4. 空匹配陷阱:空字符串 new RegExp("")匹配任何输入

    js
    console.log(new RegExp("").test("abc")); // true

进阶示例

  1. 动态构建正则表达式

    js
    const userInput = "hello";
    const dynamicRegex = new RegExp(`\\b${userInput}\\b`, "i"); // /\bhello\b/i
    console.log(dynamicRegex.test("Hello world")); // true
  2. 复制正则表达式

    js
    const original = /abc/g;
    const copy = new RegExp(original); // 复制模式
    const withNewFlags = new RegExp(original, "i"); // 覆盖标志为 i

方法

exec()@

re.exec()(str),用于执行正则匹配并返回详细匹配信息

  • strstring,要搜索的目标字符串。

  • 返回:

  • resultarray|null,返回包含匹配结果的数组(匹配成功)或 null(匹配失败)。

基本示例

  1. 基础匹配

    js
    const phoneRe = /(\d{3})-(\d{4})/;
    const result = phoneRe.exec('Tel: 123-4567');
    console.log(result[0]); // "123-4567"
    console.log(result[1]); // "123"
    console.log(result[2]); // "4567"
    console.log(result.index); // 5

核心特性

  1. 匹配成功时的返回数组结构

    js
    [
      '匹配的完整文本',      // 索引 0
      '捕获组1内容',         // 索引 1(如果有捕获组)
      '捕获组2内容',         // 索引 2
      ...,
      index: 匹配起始位置,    // 数值属性
      input: '原始输入字符串', // 字符串属性
      groups: {              // 对象属性(命名捕获组)
        '组名': '值',
        ...
      }
    ]
  2. 执行机制详解

    1. 无全局标志 (g) 时

      • 始终返回第一个匹配结果
      • 忽略 lastIndex 属性
      js
      const re = /a(b)/;
      const result = re.exec('abc abc');
      // [
      //   'ab',
      //   'b',
      //   index: 0,
      //   input: 'abc abc',
      //   groups: undefined
      // ]
    2. 有全局标志 (g) 时

      • 维护 lastIndex 属性(记录下次匹配起始位置)
      • 连续调用可遍历所有匹配
      js
      const re = /a(b)/g;
      let result;
      
      while ((result = re.exec('abc abc')) !== null) {
        console.log(`在位置 ${result.index} 找到: ${result[0]}`);
      }
      // 在位置 0 找到: ab
      // 在位置 4 找到: ab
    3. 粘滞模式 (y) 时

      • 强制从 lastIndex 开始匹配
      • 匹配失败时重置 lastIndex 为 0
      js
      const re = /^a/y;
      re.lastIndex = 1; // 从索引 1 开始匹配
      
      console.log(re.exec('baa')); // null(索引1位置是 'a',但要求开头必须是 'a')
      console.log(re.lastIndex);   // 0(匹配失败时自动重置为0)

注意事项

  1. 全局匹配状态

    使用 g 标志时,正则对象会维护 lastIndex 属性,不要复用同一个正则对象执行不同字符串的全局匹配:

    js
    const re = /a/g;
    re.exec('abc'); // 匹配成功
    re.exec('axyz'); // 从 lastIndex=1 开始匹配 'xyz' → 失败
  2. 性能优化

    避免在循环中重复创建正则对象:

    js
    // 错误做法(每次循环都创建新正则)
    for (let i=0; i<1000; i++) {
      /a/g.exec(str);
    }
    
    // 正确做法(提前创建)
    const re = /a/g;
    for (let i=0; i<1000; i++) {
      re.lastIndex = 0; // 重置指针
      re.exec(str);
    }

进阶示例

  1. 命名捕获组

    js
    const re = /(?<year>\d{4})-(?<month>\d{2})/;
    const result = re.exec('2023-10');
    console.log(result.groups.year);  // "2023"
    console.log(result.groups.month); // "10"
  2. 空匹配

    js
    const re = /a*/;
    console.log(re.exec('b')); 
    // [ '', index: 0, input: 'b', groups: undefined ]
  3. 多行匹配

    js
    const re = /^a/m; // 多行模式
    const result = re.exec('b\na');
    console.log(result.index); // 2(匹配到第二行开头的 'a')

test()@

re.test()(str),用于快速检测字符串中是否存在匹配模式

  • strstring,被测试匹配的字符串。

  • 返回:

  • isMatchedboolean,返回符串中是否存在至少一个匹配项。

基本示例

  1. 简单验证

    js
    // 验证字符串是否包含数字
    const hasDigit = /\d/;
    console.log(hasDigit.test("Hello123")); // true
    console.log(hasDigit.test("Hello"));    // false

核心特性

  1. 执行机制详解

    1. 无全局标志 (g) 时

      • 始终检测第一个匹配
      • 不修改正则对象的 lastIndex 属性
      • 多次调用结果相同
      js
      const re = /a/;
      console.log(re.test("abc")); // true
      console.log(re.test("abc")); // true(结果不变)
      console.log(re.lastIndex);   // 0(未被修改)
    2. 有全局标志 (g) 时

      • 维护 lastIndex 属性(记录下次匹配起始位置)
      • 连续调用可遍历所有匹配
      js
      const re = /a/g;
      const str = "aba";
      
      console.log(re.test(str)); // true(位置0)
      console.log(re.lastIndex); // 1
      
      console.log(re.test(str)); // true(位置2)
      console.log(re.lastIndex); // 3
      
      console.log(re.test(str)); // false(无更多匹配)
      console.log(re.lastIndex); // 0(自动重置)
    3. 粘滞模式 (y) 时

      • 强制从 lastIndex 精确位置开始匹配
      • 匹配失败则重置 lastIndex 为 0
      js
      const re = /a/y;
      re.lastIndex = 1;
      
      console.log(re.test("baa")); // true(索引1匹配)
      console.log(re.lastIndex);   // 2
      
      re.lastIndex = 3;
      console.log(re.test("baa")); // false(超出范围)
      console.log(re.lastIndex);   // 0(自动重置)

进阶示例

  1. 粘滞模式精确匹配

    js
    // 检测连续出现的数字
    const re = /\d+/y;
    re.lastIndex = 4; // 从索引4开始
    
    console.log(re.test("123abc456")); // false(索引4是字母b)
    console.log(re.test("123 456"));   // true(索引4是空格后的4)
  2. 空匹配:空模式始终返回 true(包括空字符串)

    js
    // 空模式始终返回 true(包括空字符串)
    console.log(RegExp("").test("abc")); // true
    console.log(RegExp("").test(""));    // true
  3. 多行匹配

    js
    // 检测每行是否以数字开头
    const re = /^\d/m;
    console.log(re.test("1st line\n2nd line")); // true
    console.log(re.test("abc\n123"));           // true(第二行匹配)