正则表达式高级用法: 分组

分组的使用场景

在书写正则表达式时,通常情况下,我们有两种场景会使用到分组。
一是:对一个子表达式进行重复;二是:想要获取到子表达式匹配到的内容。

  • 对子表达式进行重复

如果需要重复单个字符,直接在字符后面加上限定符即可,例如 a+ 表示匹配1个或一个以上的a,a?表示匹配0个或1个a。
但是我们如果要对多个字符进行重复的话,就需要用到 分组
比如:(ab){3} 表示 ab 字符重复3次

正则中常用的限定符如下:

表达式说明
X ?X ,一次或一次也没有
X *X ,零次或多次
X +X ,一次或多次
X { n }X ,恰好 n
X { n ,}X ,至少 n
X { n , m }X ,至少 n 次,但是不超过 m
  • 获取到子表达式匹配到的内容

比如表达式: [a-z]*\d*[a-z]*,它表示a-z的字符重复0到多次,后面紧跟0到多个数字,后面再跟上多个a-z的字符。
显然,字符串 abcd324232efg 是满足匹配的串。那么,如果我们只想要获取到匹配串中数字 324232 后面的串 efg 呢?

这时,就可以通过分组的方式来改写正则表达式: [a-z]*\d*([a-z]*)。这样,我们就可以通过获取第 1 个分组匹配到的内容来达到目的。

分组的使用方法

正则中通过小括号“()”来指定需要重复的子表达式,然后再加上限定符对这个子表达式进行重复。

例如:(abc)? 表示0个或1个abc 。
一组括号里面的表达式就表示一个分组 。

捕获组

分组可以分为两种形式,捕获组非捕获组

捕获组和非捕获组的区别就是:捕获组表示的分组会捕获文本(即:匹配字符),而非捕获组表示的分组不会捕获文本。

捕获组可以通过从左到右计算其开括号来编号
例如,在表达式 (A)(B(C)) 中,存在四个这样的组:

分组编号分组编号对应的子表达式
0(A)(B(C))
1(A)
2(B(C))
3(C)

注意:第0个分组始终代表整个表达式

分组的序号可以通过 Back 引用(反向引用) 在表达式中使用,也可以在匹配操作完成后从匹配器检索出分组匹配到的内容。
反向引用的知识将会在后续的文章中进行分析。

分组的使用实例

在一个完整的正则中,如果我们只想获取到某个子表达式匹配到的内容,就可以通过分组来达到目的。

比如:
待匹配串:abcd324232efg
想要获取到这个字符串中第二次连续出现的字母子串efg

我们可以通过分组的方式书写正则: [a-z]*\d*([a-z]*)
可以看到,我们通过子表达式([a-z]*)来匹配第二次连续出现之母的子串,并且通过()添加了分组,这样,我们就可以通过分组来获取到相应的匹配内容了。

具体的获取方法不同的语言的语法可能会有差异,但是原理是相通的。
下面就来看一下 javascript 和 java 中是如何进行处理的?

javascript 获取分组内容

var str = "abcd324232efg";
var reg = new RegExp("([a-z]*)(\\d*)([a-z]*)");
var arr = str.match(reg);
// 显示匹配到的分组内容
alert(arr[0] + "===" + arr[1] + "===" + arr[2] + "===" + arr[3]);
alert(RegExp.$1 + "-----" + RegExp.$2 + "----" + RegExp.$3);  

上面的例子中,我添加了 3 个分组。
通过 arr[n]RegExp.$n 的方式都能获取到分组匹配内容。

在 javascript 中 \d 需要进行转义

java 获取分组内容

public static void main(String[] args) {
    String str = "abcd324232efg";
    Pattern pattern = Pattern.compile("([a-z]*)(\\d*)([a-z]*)");
    Matcher matcher = pattern.matcher(str);
    if (matcher.find()) {
        System.out.println(matcher.group());
        System.out.println(matcher.group(0));
        System.out.println(matcher.group(1));
        System.out.println(matcher.group(2));
        System.out.println(matcher.group(3));
    }
}

在 java 中,通过 Matcher.group(n) 的方式拿到分组匹配内容。

在 javascript 中 \d 需要进行转义

小结

分组通常有两种使用场景:一是:对一个子表达式进行重复;二是:想要获取到子表达式匹配到的内容。

分组是通过 () 来表示的,它是通过从左到右计算其开括号来进行编号的。

更加系统的学习正则表达式的知识,请点击视频讲解:
正则表达式从入门到高手: https://edu.51cto.com/sd/59587


阅读更多文章,请关注公众号: 老王学源码
gzh_b2.png

  • 16
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
正则表达式是一种强大的文本模式匹配工具,JavaScript中也提供了丰富的正则表达式API。下面是一些正则表达式高级用法: 1. 零宽断言 零宽断言是一种特殊的正则表达式语法,用于匹配在给定位置前面或后面的内容,但并不将这些内容包含在匹配结果中。它们被称为“零宽度”因为它们不会匹配任何实际字符,只是用于查找文本而已。JavaScript中支持三种零宽断言: - (?=pattern):正向先行断言,匹配某个位置后面紧跟着指定模式的内容。 - (?!pattern):负向先行断言,匹配某个位置后面不紧跟着指定模式的内容。 - (?<=pattern):正向后行断言,匹配某个位置前面紧跟着指定模式的内容。 - (?<!pattern):负向后行断言,匹配某个位置前面不紧跟着指定模式的内容。 例如,要匹配以字母开头,且后面跟着数字和字母的字符串,可以使用正向先行断言: ``` const str = "a1b2c3"; const pattern = /^[a-z](?=[a-z0-9])/i; const result = str.match(pattern); console.log(result[0]); // "a1" ``` 2. 非捕获分组 捕获分组是指用小括号将某个模式括起来,以便后面可以引用这个匹配结果。但有时我们只想匹配某个模式,而不需要捕获它。这时可以使用非捕获分组,它的语法为 (?:pattern)。 例如,要匹配以数字开头,后面跟着一个或多个连续的数字和句号(.),然后以数字结尾的字符串,可以使用非捕获分组: ``` const str = "123.456.789"; const pattern = /^(?:\d+\.)+\d+$/; const result = str.match(pattern); console.log(result[0]); // "123.456.789" ``` 3. 贪婪匹配与非贪婪匹配 默认情况下,正则表达式是贪婪匹配,即尽可能多地匹配符合模式的文本。但有时我们需要非贪婪匹配,即只匹配符合模式的最短文本。这时可以在重复匹配符号后面加上问号(?)。 例如,要匹配以左括号开头,右括号结尾的最短字符串,可以使用非贪婪匹配: ``` const str = "(a(b)c)d"; const pattern = /\(.*?\)/; const result = str.match(pattern); console.log(result[0]); // "(b)" ``` 以上是一些JavaScript正则表达式高级用法,希望能对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

老王学源码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值