正则表达式是一种用来匹配和处理文本的强大工具,它可以用来验证输入,提取信息,替换文本,等等。在正则表达式中,有一种特殊的符号叫做分组,它可以用来把一个或多个字符组合在一起,形成一个子表达式。分组有两种类型:捕获分组和非捕获分组。本文将介绍这两种分组的区别和用法。
捕获分组
捕获分组是用圆括号()
包围的子表达式,它可以用来匹配一个特定的模式,并且把匹配的结果保存在一个变量中,供后续使用。例如,如果我们想要匹配一个日期格式,如2023-06-15
,我们可以使用这样的正则表达式:(\d{4})-(\d{2})-(\d{2})
这个表达式中有三个捕获分组,分别是(\d{4})
,(\d{2})
和(\d{2})
,它们分别匹配四位数字,两位数字和两位数字。当这个表达式匹配到一个日期时,它会把匹配的结果保存在三个变量中,通常称为$1
,$2
和$3
。例如,在JavaScript中,我们可以这样使用这个表达式:
let date = "2023-06-15";
let regex = /(\d{4})-(\d{2})-(\d{2})/;
let match = date.match(regex);
console.log(match[1]); // 2023
console.log(match[2]); // 06
console.log(match[3]); // 15
捕获分组不仅可以用来提取信息,还可以用来替换文本。例如,如果我们想要把日期格式从2023-06-15
改为15/06/2023
,我们可以使用这样的正则表达式:(\d{4})-(\d{2})-(\d{2})
然后把替换的字符串设为$3/$2/$1
。例如,在JavaScript中,我们可以这样使用这个表达式:
let date = "2023-06-15";
let regex = /(\d{4})-(\d{2})-(\d{2})/;
let newDate = date.replace(regex, "$3/$2/$1");
console.log(newDate); // 15/06/2023
捕获分组还可以分为具名分组和匿名分组,刚才介绍了匿名分组,接下来说一下具名分组。
顾名思义,具名分组可以给组进行命名,从而避免使用$加数字的方式增加开发难度。
const groups = "06-15-2023".match(/(?<month>\d{2})-(?<day>\d{2})-(?<year>\d{4})/).groups
// {month: "06", day: "15", year: "2023"}
const {day, month, year} = groups
console.table({"year":year,"month":month,"day":day})
索引 | 值 |
---|---|
非捕获分组
非捕获分组是在捕获分组的左括号右侧加上?:,也就是(?:)
,它也可以用来匹配一个特定的模式,但是不会把匹配的结果保存在变量中。非捕获分组主要有两个作用:一是提高性能,因为不需要保存匹配的结果;二是避免干扰其他捕获分组的编号。
那什么时候要用到非捕获分组呢?
情形一:
当需要使用括号来分组或者限定多选结构或者量词的作用范围,但又不需要提取或者引用括号内的内容时,可以使用非捕获组来提高效率和节省内存。例如,下面的正则表达式可以匹配一个整数或者一个小数,其中第一个括号是一个非捕获组,用于限定竖线的作用范围,第二个括号是一个捕获组,用于提取小数点后面的数字:/^(?:\d+|\d+\.(\d+))$/
情形二:
当需要使用命名捕获组来为提取的内容命名,但又不想影响原有的捕获组编号时,可以使用非捕获组来避免编号混乱。例如,下面的正则表达式可以匹配一个日期,其中第一个括号是一个命名捕获组,用于提取年份,第二个括号是一个非捕获组,用于限定斜线的作用范围,第三个括号是一个普通捕获组,用于提取月份:/(?<year>\d{4})(?:\/)(\d{2})/
情形三:
当需要使用反向引用来匹配成对的标签或者引号,但又不想让反向引用被替换时,可以使用非捕获组来保留反向引用的内容。例如,下面的正则表达式可以匹配HTML中的标签,其中第一个括号是一个捕获组,用于反向引用,第二个括号是一个非捕获组,用于限定问号量词的作用范围:/<(\w+)[^>]*>(?:.*?<\/\1>)?/g
总结
捕获分组和非捕获分组是正则表达式中的两种重要的符号,它们可以用来匹配和处理文本的不同部分。捕获分组可以用来保存匹配的结果,供后续使用;非捕获分组可以用来提高性能和避免干扰其他捕获分组的编号。在使用正则表达式时,应该根据需要选择合适的分组类型。
往期精彩:
3、简单易学!使用 Node.js 编写爬虫,跟着教程一步步实现!
评论区