Skip to content

进阶型元字符

元字符中文名称匹配对象
(char)捕获型括号限定多选结构、分组、捕获结果
(?:char)非捕获型括号匹配char,但不捕获该结果
(?>char)固化分组(暂不支持)匹配char,且不交还还分组里的任何字符
(?<name>)命名捕获命名捕获分组内容,并通过name调用捕获内容

注意

  • char为要匹配的字符串或表达式;
  • name为合法的JavaScript标识符,描述了捕获的内容;
  • 固化分组(?>char)至今不被JavaScript支持。

语法声明

本页示例均使用的JavaScript正则语法声明 const regexp = /pattern/flags:

捕获型括号 ()

多层捕获括号嵌套时的捕获顺序:

  1. 若左侧的捕获括号内无嵌套捕获括号,则按表达式中出现的顺序从左到右依次捕获
  2. 若左侧的捕获括号内有嵌套捕获括号,则先在该处按从外到内的顺序依次捕获,再按表达式中出现的顺序从左到右依次捕获
  3. 若在从左到右的捕获中出现了上面 2 中的情况,依然按照 2 中的方法处理; 出现 1 中的情况,则按 1 中的方法处理。

为了更好的理解捕获顺序,举个简单的例子:

javascript
const str = "Design by AchooLuv";
const regexp = /(ac(hoo))(luv)/i; // 捕获分组顺序:['Achoo', 'hoo', 'Luv']
const result = str.match(regexp);
console.log(result); // 匹配结果为: AchooLuv

从匹配结果发现,捕获的顺序依次是:['Achoo', 'hoo', 'Luv'],符合前面表述的:从外到内,从左到右

表达式内的反向引用

在正则表达式内部我们可以使用反向引用捕获分组内容,其格式: \n

注意

n为数字,从1开始计数,表示第n个捕获分组。

javascript
const str = "Design by AchooLuvAchooLuvAchooLuv";
const regexp = /(achoo)(luv)\1/i; // 捕获分组顺序:['Achoo', 'Luv']
const result = str.match(regexp);
console.log(result); // 匹配结果为: AchooLuvAchoo

在正则表达式中我们通过\1引用了捕获分组内容(achoo),所以此时的匹配结果为'AchooLuvAchoo'

反向引用被捕获后也可被引用

javascript
const str = "Design by AchooLuvAchooLuvAchooLuv";
const regexp = /(achoo)(luv)(\1)(\2)\3/i; // 捕获分组顺序:['Achoo', 'Luv', 'Achoo', 'Luv']
const result = str.match(regexp);
console.log(result); // 匹配结果为: AchooLuvAchooLuvAchoo

我们使用\1引用表达式中的(achoo),并将\1捕获,然后使用\3引用表达式中的(\1)

通过$1~$9直接引用捕获内容

比如我们视图将AchooLuv改成LuvAchoo

javascript
const str = "Design by AchooLuv";
const result = str.replace(/(achoo)(luv)/i, "$2$1");
console.log(result); // 匹配结果为: Design by LuvAchoo

// 也可以通过全局对象RegExp来引用
console.log(RegExp.$1, RegExp.$2); // 依次输出:Achoo Luv

非捕获型括号 (?:)

顾名思义,非捕获型括号只匹配内容,不会捕获内容,所以也无法引用其匹配的内容。

javascript
const str = "Design by AchooLuv";
const regexp = /(?:achoo)(luv)/i;
const result = str.match(regexp);
console.log(RegExp.$1); // 输出结果为: Luv

固化分组 (?>)

很遗憾

JavaScript至今不支持固化分组功能!!!

命名捕获 (?<>)

注意

命名捕获是ES9才正式支持的正则新特性,使用时需要注意浏览器支持情况!!!

假设我们想在一字符串中提取按YYYY-MM-DD格式表示的时间,并拿到对应的 ,像这样(此处简化了字符串):

javascript
const regexp = /(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})/;
const {
  groups: { day, month, year },
} = regexp.exec("1995-05-26"); // 解构赋值
console.log(year, month, day); // 输出结果:1995 05 26

可以看见我们的命名捕获生效了,在解构赋值时,命名的变量都取到了对应的值。