正则表达式中分组功能高级用法

通过将部分正则表达式用括号括住来实现分组捕获的用法大部分人都很熟悉,如/.+(\d+).+/捕获字符串中的所有数字部分,然后通过组号就可以抽取出各分组匹配的字符文本或者通过反向引用的方式对分组中的文本进行替换。但是除了不同的分组用法以外,正则表达式引擎还提供了一些高级的分组功能,下面介绍部分比较常用的特殊分组:

1、非捕获分组( non-capturing group)

使用语法:(?:regex)这里的?和:都是语法的组成部分;这种分组正则表达式引擎不会捕获它所匹配的内容即不会为非捕获型分组分配组号;

样例说明:Set(?:Value)?表达式匹配SetValue或者Set,但是不能通过group(1)的方式获取Value文本串,Set(Value)?则可以获取的到

语言支持说明:java和javascript都支持

 1 public static void noCaptureGroup(){
 2         Pattern pattern = Pattern.compile("(?:(\\d+))?\\s?([a-zA-Z]+)?.+");
 3         String source = "2133 fdsdee4333";
 4         Matcher matcher = pattern.matcher(source);
 5         if(matcher.matches()){
 6             for(int i=0;i<=matcher.groupCount();i++){
 7                 System.out.println("group "+i+":"+matcher.group(i));
 8             }
 9         }
10     }

2、原子分组(Atomic group)

使用语法:(?>regex)这里的?和>都是语法的组成部分;原子分组是贪婪的匹配,当文本和这个分组匹配的成功后,正则表达式引擎在匹配后面的表达式时不会发生回溯行为及尽可能多的匹配,注意这个分组的贪婪行为和++这种贪婪匹配略有不同,++只能对正则表达式字符进行多次贪婪匹配如(bc|b)是没办法利用++进行贪婪匹配的而(\w++)可以,如下面代码中的正则表达式如果换成:(\\d+)\\s+(\\w++)(\\w)匹配则会失败。

语言支持说明:java支持,javascript不支持

 1 public static void atomicGroup(){
 2         Pattern pattern = Pattern.compile("(\\d+)\\s+(?>bc|b)(\\w)");
 3         String source = "543543   bcc";  //而“543543   bc” 却匹配失败因为bc已经被原子分组匹配了,当(\\w)进行匹配的时候前面的分组由于是贪婪型匹配所以不会突出以匹配的字符
 4         Matcher matcher = pattern.matcher(source);
 5         if(matcher.matches()){
 6             for(int i=0;i<=matcher.groupCount();i++){
 7                 System.out.println("group "+i+":"+matcher.group(i));
 8             }
 9         }
10     }

3、正前向查找分组(Positive lookahead)

使用语法:(?=regex)这里的?和=都是语法的组成部分;可以理解成在正前向分组里面的表达式匹配成功后,正则表达式引擎回溯到正前向分组开始匹配的字符处再进行后面正则表达式的匹配,如果后面的正则表达式也匹配成功,整个匹配过程才算成功。注意这里的正前向查找分组为非捕获型分组即不会占用分组号

例如下面的样例代码中\\s+匹配完数字后面的所有空格后(?=s)和s字符匹配成功,但这个时候指针指向t字符,当进行(\\w+)这个分组匹配时正则表达式引擎会将指针回溯到s处才开始(\\w+)分组的匹配过程。

语言支持说明:java支持,javascript不支持

 1 public static void positvieLookaheadGroup(){
 2         Pattern pattern = Pattern.compile("(\\d+)\\s+(?=s)(\\w+)");
 3         String source = "543543   streets";        //"543543   ttreets" 匹配失败
 4         Matcher matcher = pattern.matcher(source);
 5         if(matcher.matches()){
 6             for(int i=0;i<=matcher.groupCount();i++){
 7                 System.out.println("group "+i+":"+matcher.group(i));
 8             }
 9         }
10     }

4、负前向查找分组(Negative lookahead)

使用语法:(?!regex)这里的?和!都是语法的组成部分;这种分组功能和正前向查找分组一样,唯一的不同就是当前向查找分组里面的正则表达式匹配失败的时候才继续后面的匹配过程

语言支持说明:java支持,javascript不支持

 1 public static void negtiveLookaheadGroup(){
 2         Pattern pattern = Pattern.compile("(\\d+)\\s+(?!s)(\\w+)");
 3         String source = "543543   ttreets";  //如"543543   streets" 匹配失败
 4         Matcher matcher = pattern.matcher(source);
 5         if(matcher.matches()){
 6             for(int i=0;i<=matcher.groupCount();i++){
 7                 System.out.println("group "+i+":"+matcher.group(i));
 8             }
 9         }
10     }

5、正后向查找分组(Positive lookbehind)

使用语法:(?<=regex)这里的?和<=都是语法的组成部分;可以理解成在正后向查找分组前面的正则表达式匹配成功后,正则表达式引擎从最后的位置往字符串左边进行回溯然后和(?<=regex)进行匹配,如果匹配失败则整个匹配过程失败;如果匹配成功,则将指针移动到正后向查找分组开始进行匹配的位置继续进行后面正则表达式的匹配过程。注意这里的正前向查找分组为非捕获型分组即不会占用分组号。

例如下面的样例代码中\\s+匹配完数字后面的所有空格后,指针指向s字符,然后进行回溯(?<=\\s)和最后一个空格字符匹配成功,但这个时候指针指向s字符前面的空格,然后正则表达式将指针重新移动到s字符处再进行(\\w+)分组的匹配过程。

语言支持说明:java支持,javascript不支持

 1 public static void positiveLookbehandGroup(){
 2         Pattern pattern = Pattern.compile("(\\d+)\\s+(?<=\\s)(\\w+)");
 3         String source = "543543   ttreets";  //"543543   streets" 匹配失败
 4         Matcher matcher = pattern.matcher(source);
 5         if(matcher.matches()){
 6             for(int i=0;i<=matcher.groupCount();i++){
 7                 System.out.println("group "+i+":"+matcher.group(i));
 8             }
 9         }
10     }

6、负后向查找分组(Negative lookbehind)

使用语法:(?<!regex)这里的?和<!都是语法的组成部分;这种分组功能和正负向查找分组一样,唯一的不同就是当负后向查找分组里面的正则表达式匹配失败的时候才继续后面的匹配过程

语言支持说明:java支持,javascript不支持

 1 public static void negtiveLookbehandGroup(){
 2         Pattern pattern = Pattern.compile("(\\d+)\\s+(?<!s)(\\w+)");
 3         String source = "543543   ttreets";  //如果正则表达式为(\\d+)\\s+(?<!\\s)(\\w+)则匹配失败
 4         Matcher matcher = pattern.matcher(source);
 5         if(matcher.matches()){
 6             for(int i=0;i<=matcher.groupCount();i++){
 7                 System.out.println("group "+i+":"+matcher.group(i));
 8             }
 9         }
10     }

 7、参考资料:

http://www.cnblogs.com/javaminer/p/3503389.html

http://www.regular-expressions.info/refadv.html

时间: 2024-12-12 09:53:41

正则表达式中分组功能高级用法的相关文章

详解Vue中watch的高级用法

我们通过实例代码给大家分享了Vue中watch的高级用法,对此知识点有需要的朋友可以跟着学习下. 假设有如下代码: 上面的代码的效果是,当我们输入firstName后,wacth监听每次修改变化的新值,然后计算输出fullName. handler方法和immediate属性 这里 watch 的一个特点是,最初绑定的时候是不会执行的,要等到 firstName 改变时才执行监听计算.那我们想要一开始就让他最初绑定的时候就执行改怎么办呢?我们需要修改一下我们的 watch 写法,修改过后的 wa

如何解决python的re模块group、groups与findall遇见正则表达式中分组&quot;()&quot;后产生的”眩晕反应“

转载请注明出处:https://www.cnblogs.com/oceanicstar/p/9244783.html 直接先上例子 >>> re.search('(book+)', 'mebookbookme').groups() ('book',) >>> re.search('(book+)', 'mebookbookme').group() 'book' >>> re.search('(book)+', 'mebookbookme').group

正则表达式中-分组构造

分组构造 捕获或非捕获 匹配的子表达式 捕获 命名匹配的子表达式 捕获 平衡组定义 捕获 非捕获组 非捕获 组选项 非捕获 零宽度正预测先行断言 非捕获 零宽度负预测先行断言 非捕获 零宽度正回顾后发断言 非捕获 零宽度负回顾后发断言 非捕获 非回溯子表达式 非捕获 表4.常用分组语法 分类 代码/语法 说明 捕获 (exp) 匹配exp,并捕获文本到自动命名的组里 (?<name>exp) 匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name'exp) (?:exp) 匹配

SQL语句中的select高级用法

为了更好的了解下面的知识点,我们先创建两张表并插入数据. # 学生表 +----+-----------+------+--------+--------+--------+-----------+ | id | name | age | height | gender | cls_id | is_delete | +----+-----------+------+--------+--------+--------+-----------+ | 1 | 小明 | 18 | 180.00 | 女

Vue中watch的高级用法

<template> <div> <input type="text" v-model="value"> </div> </template> <script> export default { data() { return { value:null } }, created(){ this.test() }, methods: { test(){ console.log("第一个加

ios中webview的高级用法

转自:http://www.cnblogs.com/gcb999/p/3178728.html 框架: webview与js的通信框架 #import "MJViewController.h" #import "MBProgressHUD+Add.h" @interface MJViewController () @end @implementation MJViewController - (void)viewDidLoad { [super viewDidLoa

Net中事件的高级用法之三

1.事件的高级应用 使用事件可以解除代码耦合 2.事件高级应用实例 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MyEvent { public delegate void MiaoEventDelegate(); public class Cat { public event MiaoEventDelegate MiaoEventHandler;

RAC中常见的高级用法-bind方法

RAC操作思想: Hook(钩子)思想 RAC核心方法:bind bind方法 假设想监听文本框的内容,并且在每次输出结果的时候,都在文本框的内容拼接一段文字“输出:” 方式一:在返回结果后,拼接. [_textField.rac_textSignal subscribeNext:^(id x) { NSLog(@"输出:%@",x); }]; 方式二:在返回结果前,拼接,使用RAC中bind方法做处理. bind方法参数:需要传入一个返回值是RACStreamBindBlock的bl

RAC中常见的高级用法-过滤

filter 过滤信号,使用它可以获取满足条件的信号. - (void)filter { //只有当我们文本框内容长度大于5才想要获取文本框的内容 [[_passWord.rac_textSignal filter:^BOOL(id value) { //value:源信号的内容 return [value length] > 5; //返回值就是过滤的条件,只有满足这个条件才能获取到内容 }] subscribeNext:^(id x) { NSLog(@"%@", x); }