进阶型元字符
元字符 | 中文名称 | 匹配对象 |
---|---|---|
(char) | 捕获型括号 | 限定多选结构、分组、捕获结果 |
(?:char) | 非捕获型括号 | 匹配char ,但不捕获该结果 |
(?>char) | 固化分组(暂不支持) | 匹配char ,且不交还 还分组里的任何字符 |
(?<name>) | 命名捕获 | 命名捕获分组内容,并通过name 调用捕获内容 |
注意
char
为要匹配的字符串或表达式;name
为合法的JavaScript
标识符,描述了捕获的内容;- 固化分组
(?>char)
至今不被JavaScript
支持。
语法声明
本页示例均使用的JavaScript
正则语法声明 const regexp = /pattern/flags
:
捕获型括号 ()
多层捕获括号嵌套时的捕获顺序:
- 若左侧的捕获括号内无嵌套捕获括号,则按表达式中出现的顺序
从左到右依次捕获
; - 若左侧的捕获括号内有嵌套捕获括号,则先在该处按
从外到内的顺序依次捕获
,再按表达式中出现的顺序从左到右依次捕获
; - 若在从左到右的捕获中出现了上面 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
可以看见我们的命名捕获生效了,在解构赋值时,命名的变量都取到了对应的值。