正则表达式——捕获分组(capture group)(Java代码)

本文详细介绍了正则表达式的捕获组,包括普通捕获组、命名捕获组、普通捕获组与命名捕获组混用及非捕获组的概念和使用方式,并给出了Java和C#的不同处理规则。通过实例代码演示了如何在正则表达式中捕获和使用这些分组,帮助理解正则表达式中的分组机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

正则大神主页:https://blog.youkuaiyun.com/lxcnn?t=1

正则表达式入门教程:https://deerchao.cn/tutorials/regex/regex.htm#top

上述两个博客的文章都是以C#为基础写作的,在普通捕获组与命名捕获组的混用上,与Java有所不同

正则运行测试网址:https://regex101.com/

正则中,每个用于匹配字符的()都是一个子表达式,可以被捕获分组捕获到,从而在正则表达式内或表达式外进行引用。环视使用了(),但是它是用来匹配位置信息的,所以不会被捕获;还有就是使用(?:expression)来主动忽略分组。

更新
在正则表达式本身中使用分组,默认编号分组-\d{4}([:-])\d{2}\1\d{2};命名分组-\d{4}(?<d>[-:])\d{2}(\k<d>)\d{2}

普通捕获组

正则表达式中,普通捕获组是按照(即左括号出现的顺序进行分组。对类似“2016-01-06”格式的日期进行简单匹配并分组,暂不不考虑闰年等问题。

分组分组内容
分组0(\d{4})-(\d{2})-(\d{2})
分组1\d{4}
分组2\d{2}
分组3\d{2}

对于所有的正则表达式,捕获组0都是正则表达式匹配的全部内容,然后第一对括号内包含的匹配内容是捕获组1,第二对括号内是捕获组2,第三对括号内是捕获组3.

Java实例代码如下:

String str = "2016-01-06";
Pattern pattern = Pattern.compile("(\\d{4})-(\\d{2})-(\\d{2})");
Matcher matcher = pattern.matcher(str);
if (matcher.find()){
    System.out.println(matcher.group(0));
    System.out.println(matcher.group(1));
    System.out.println(matcher.group(2));
    System.out.println(matcher.group(3));
}
// 结果如下:
// 2016-01-06
// 2016
// 01
// 06

命名捕获组

还是对日期进行正则匹配,表达式本身不变,改为使用命名捕获组组。命名捕获组与普通捕获组的区别在于,在()内添加捕获组的名字,方便后续使用。格式为:(?<name>expression)。name区分大小写。

分组分组内容
分组year\d{4}
分组month\d{2}
分组day\d{2}

通过在()内添加?<name>,对捕获组进行命名,从而更方便后续对匹配内容的使用。

Java实例代码如下:

String str = "2016-01-06";
Pattern pattern = Pattern.compile("(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})");
Matcher matcher = pattern.matcher(str);
if (matcher.find()){
    System.out.println(matcher.group("year"));
    System.out.println(matcher.group("month"));
    System.out.println(matcher.group("day"));
}
// 结果如下:
// 2016
// 01
// 06

普通捕获组与命名捕获组混用

当普通捕获组与命名捕获组混用时,各个语言的具体规则略有差异。

在Java中,不管此捕获组是否被命名,依旧按照普通捕获组的规则进行排序,然后被命名的分组同时也可以作为命名捕获组使用。

普通捕获组命名捕获组分组内容
分组0(\d{4})-(\d{2})-(\d{2})
分组1\d{4}
分组2分组month\d{2}
分组3\d{2}

Java实例代码如下:

String str = "2016-01-06";
Pattern pattern = Pattern.compile("(\\d{4})-(?<month>\\d{2})-(\\d{2})");
Matcher matcher = pattern.matcher(str);
if (matcher.find()){
    System.out.println(matcher.group(0));
    System.out.println(matcher.group(1));
    System.out.println(matcher.group(2));
    System.out.println(matcher.group(3));
    System.out.println(matcher.group("month"));
}
// 结果如下:
// 2016-01-06
// 2016
// 01
// 06
// 01

通过上述代码可以看到,月份01既可以作为普通捕获组2使用,同时也可以作为命名捕获组month使用。

C#的普通捕获组与命名捕获组混用时的规则与Java不一致。在C#中,会先去除已被命名的捕获组,对剩余的所有捕获组按照普通捕获组的规则进行排序,然后再对命名捕获组进行排序,因此在C#中,所有命名捕获组的序号都会大于普通捕获组的序号。

在上述例子中,已被命名为month的捕获组,在C#中序号应该是分组3,而不是分组2,分组2应该是用于匹配日期的子表达式。

C#普通捕获与命名捕获混用官方规则

Java普通捕获与命名捕获混用官方规则

非捕获组

在正则中,可以选择忽略某些捕获组,不将它们列入分组捕获排序中,从而更方便的获取我们想要匹配的内容。子表达式中增加?:,会被正则引擎忽略,不被计入捕获组中。(?:expression)这种格式的子表达式被称为非捕获组。

普通捕获组非捕获组分组内容
分组0(\d{4})-(\d{2})-(\d{2})
分组1\d{4}
非捕获组?:\d{2}
分组2\d{2}

Java实例代码如下:

String str = "2016-01-06";
Pattern pattern = Pattern.compile("(\\d{4})-(?:\\d{2})-(\\d{2})");
Matcher matcher = pattern.matcher(str);
if (matcher.find()){
    System.out.println(matcher.group(0));
    System.out.println(matcher.group(1));
    System.out.println(matcher.group(2));
    System.out.println(matcher.group(3));
}
// 结果如下:
// 2016-01-06
// 2016
// 06
// Exception in thread "main" java.lang.IndexOutOfBoundsException: No group 3

通过代码可以看到,匹配月份的子表达式被正则引擎忽略,并没有计入捕获组的排序中。其他子表达式依旧按照正常的分组排序规则进行排序,匹配日期的子表达式作为分组2被统计,导致缺少分组3,在获取时抛异常。

总结

正则表达式的捕获组内容包括有普通捕获组,命名捕获组,普通捕获组与命名捕获组混用,非捕获组。

上一篇:贪婪、非贪婪与占有模式
下一篇:反向引用

### 大模型对齐微调DPO方法详解 #### DPO简介 直接偏好优化(Direct Preference Optimization, DPO)是一种用于改进大型语言模型行为的技术,该技术通过结合奖励模型训练和强化学习来提升训练效率与稳定性[^1]。 #### 实现机制 DPO的核心在于它能够依据人类反馈调整模型输出的概率分布。具体来说,当给定一对候选响应时,DPO试图使更受偏好的那个选项具有更高的生成概率。这种方法不仅简化了传统强化学习所需的复杂环境设置,而且显著增强了模型对于多样化指令的理解能力和执行精度[^2]。 #### PAI平台上的实践指南 为了便于开发者实施这一先进理念,在PAI-QuickStart框架下提供了详尽的操作手册。这份文档覆盖了从环境配置直至完成整个微调流程所需的一切细节,包括但不限于数据准备、参数设定以及性能评估等方面的内容。尤其值得注意的是,针对阿里云最新发布的开源LLM——Qwen2系列,文中给出了具体的实例说明,使得即使是初次接触此类工作的用户也能顺利上手。 ```python from transformers import AutoModelForCausalLM, Trainer, TrainingArguments model_name_or_path = "qwen-model-name" tokenizer_name = model_name_or_path training_args = TrainingArguments( output_dir="./results", per_device_train_batch_size=8, num_train_epochs=3, ) trainer = Trainer( model_init=lambda: AutoModelForCausalLM.from_pretrained(model_name_or_path), args=training_args, train_dataset=train_dataset, ) # 假设已经定义好了train_dataset trainer.train() ``` 这段代码片段展示了如何使用Hugging Face库加载预训练模型并对其进行微调的过程。虽然这里展示的例子并不完全对应于DPO的具体实现方式,但它提供了一个基础模板供进一步定制化开发之用[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值