参考:http://blog.chenlb.com/2008/12/java-regular-expression-special-constructs-ornon-capturing-group.html

在 java api 文档中的正则表达式关于特殊构造(非捕获组)的说明看不懂。例如:

(?:X) X,作为非捕获组
(?idmsux-idmsux) Nothing,但是将匹配标志由 on 转为 off
(?idmsux-idmsux:X) X,作为带有给定标志 on - off 的非捕获组
(?=X) X,通过零宽度的正 lookahead
(?!X) X,通过零宽度的负 lookahead
(?<=X) X,通过零宽度的正 lookbehind
(?<!X) X,通过零宽度的负 lookbehind
(?>X) X,作为独立的非捕获组

这些字都说的很抽象。不懂……。还是搜索下去。找到 火龙果 的解释如下:

以 (? 开头,) 结尾的都称为非捕获组,在匹配完成后在内存中不保留匹配到的字符。

非捕获组的应用比较复杂,这里只能简单地说一下它们的意思。

1、(?:X) X,作为非捕获组
与捕获组 ( ) 的意思一样也是将其作为一组进行处理,与捕获组的区别在于不捕获匹配的文本,仅仅作为分组。
比如:

要匹配 123123 这个,就可以写为 (123)\1 使用反向引用,这时只能用捕获组,在匹配123 后会保留在内存中,便于反向引用;

(?:123) 在匹配完后则不会保留反向引用,区别仅在于此。不保留反向引用可以节省内存,提高效率。

(123)\1等效(?:123)123,代码示例:

 /*** outputs* 模式(123)\1* 123123*/Pattern p = Pattern.compile("(123)\\1");Matcher m = p.matcher("ad123dfe123123grr");System.out.println("模式(123)\\1");while(m.find()){System.out.println(m.group());}/*** outputs* 模式(?:123)123* 123123*/p = Pattern.compile("(?:123)123");m = p.matcher("ad123dfe123123grr");System.out.println("模式(?:123)123");while(m.find()){System.out.println(m.group());}

2、(?idmsux-idmsux)  Nothing,但是将匹配标志i d m s u x on - off
用于标志匹配,比如:表达式 (?i)abc(?-i)def 这时,(?i) 打开不区分大小写开关,abc 匹配
不区分大小地进行匹配,(?-i) 关闭标志,恢复不区分大小写,这时的 def 只能匹配 def

//(?i)忽略大小写,这个简单。但是只适合ASCII字符//当有俄文字符——小写б(大写Б)л(Л),这时要一起用(?u)p = Pattern.compile("(?i)(?u)sayбл");m = p.matcher("This is a test sayбл hello.\n"+"Wello SayБЛ \nello?");System.out.println("参数为(?i)(?u)");while(m.find()){System.out.println(m.group());}
//单行模式下,.可以匹配任何字符(包括\n)/*** outputs* hello* Wello* \nello*/p = Pattern.compile("(?s).ello");m = p.matcher("This is a test say hello.\n"+ "Wello say \nello?");System.out.println("参数为(?s)");while(m.find()){System.out.println(m.group());}
 //多行模式下,\n 或\r\n 作为行的分隔符,不匹配(.)/*** outputs:* hello* Wello*/p = Pattern.compile("(?m).ello");m = p.matcher("This is a test say hello.\n"+ "Wello say \nello?");System.out.println("参数为(?m)");while(m.find()){System.out.println(m.group());}


   //(?d)模式,启动UNIX行模式,只认 \n//UNIX 行: \n//WINDOWS 行:\r\n/*** outputs:* ello start:27end:32* ello?start:37end:42*/p = Pattern.compile("(?m)ello.");m = p.matcher("This is a test say hello\r\n"+"Wello say \nello?");System.out.println("参数为(?d)");while(m.find()){System.out.println( m.group() + "start:" + m.start() + "end:" + m.end() );}//单独使用(?m)能依据\n 和\r\n 来分行/*** outputs:* ello* start:20end:25* ello start:27end:32* ello?start:37end:42*/p = Pattern.compile("(?d)(?m)ello.");m = p.matcher("This is a test say hello\r\n"+"Wello say \nello?");System.out.println("参数为(?d)");while(m.find()){System.out.println( m.group() + "start:" + m.start() + "end:" + m.end() );}//组合使用(?d)(?m)只能依据\n 来分行

3、(?idmsux-idmsux:X)  X,作为带有给定标志 i d m s u x on - off
与上面的类似,上面的表达式,可以改写成为:(?i:abc)def,或者 (?i)abc(?-i:def)

4、(?=X) X,通过零宽度的正 lookahead
5、(?!X) X,通过零宽度的负 lookahead

(?=X) 表示当前位置(即字符的缝隙)后面允许出现的字符,比如:表示式 a(?=b),在字符串为
ab 时,可能匹配 a,后面的 (?=b) 表示,a 后面的缝隙,可以看作是零宽度。
(?!X) 表示当前位置后面不允许出现的字符

字符扫描,从左到右,所以前瞻即向右看,后瞻即向左看!

 //a(?=b),匹配a前瞻(lookahead)是b;即ab但不捕获b/*** outputs* a:start=4,end=5* a:start=9,end=10*/p = Pattern.compile("a(?=b)");m = p.matcher("aacdabaaeabdaBh");System.out.println("a(?=b)");while(m.find()){System.out.println(m.group() + ":start=" + m.start() + ",end=" + m.end());}
//a(?!b),匹配a前瞻(lookahead)是非b;即a[^b]但不捕获[^b]/*** outputs* a:start=0,end=1* a:start=1,end=2* a:start=6,end=7* a:start=7,end=8* a:start=12,end=13*/p = Pattern.compile("a(?!b)");m = p.matcher("aacdabaaeabdaBh");System.out.println("a(?!b)");while(m.find()){System.out.println(m.group() + ":start=" + m.start() + ",end=" + m.end());}

6、(? <=X) X,通过零宽度的正 lookbehind
7、(? <!X) X,通过零宽度的负 lookbehind

这两个与上面两个类似,上面两个是向后看,这个是向前看

//(?<=b)a,匹配a后瞻(lookbehind)是b;即ba但不捕获b/*** outputs* a:start=6,end=7*/p = Pattern.compile("(?<=b)a");m = p.matcher("aacdabaaeabdaBh");System.out.println("(?<=b)a");while(m.find()){System.out.println(m.group() + ":start=" + m.start() + ",end=" + m.end());}
//(?<!b)a,匹配a后瞻(lookbehind)是非b;即[^b]a但不捕获[^b]/*** outputs* a:start=0,end=1* a:start=1,end=2* a:start=4,end=5* a:start=7,end=8* a:start=9,end=10* a:start=12,end=13*/p = Pattern.compile("(?<!b)a");m = p.matcher("aacdabaaeabdaBh");System.out.println("(?<!b)a");while(m.find()){System.out.println(m.group() + ":start=" + m.start() + ",end=" + m.end());}

8、(?>X) X,作为独立的非捕获组
匹配成功不进行回溯,这个比较复杂,也侵占量词“+”可以通用,比如:\d++ 可以写为 (?>\d+)。

//(?>x)不回溯的匹配,性能优化/*** outputs* integer:start=5,end=12* insert:start=17,end=23* in:start=27,end=29*/p = Pattern.compile("\\b(?>integer|insert|in)\\b");m = p.matcher("test integer and insert of in it");System.out.println("\\b(?>integer|insert|in)\\b");while(m.find()){System.out.println(m.group() + ":start=" + m.start() + ",end=" + m.end());}

// 换了个顺序,结果大不一样!

/*** outputs* in:start=27,end=29*/p = Pattern.compile("\\b(?>in|integer|insert)\\b");m = p.matcher("test integer and insert of in it");System.out.println("\\b(?>in|integer|insert)\\b");while(m.find()){System.out.println(m.group() + ":start=" + m.start() + ",end=" + m.end());}

还没搞懂,为什么换个顺序后结果就不同了,反正别人建议是:长的放前面,短的放后面。至于原因嘛,以后懂了再说。

特殊构造(非捕获总结)相关推荐

  1. 正则表达式中的非捕获组是什么?

    非捕获组(即(?:) )如何在正则表达式中使用,它们有什么用? #1楼 在复杂的正则表达式中,您可能会希望使用大量的组,其中一些用于重复匹配,而另一些则提供反向引用. 默认情况下,与每个组匹配的文本会 ...

  2. 【正则表达式系列】一些概念(字符组、捕获组、非捕获组)

    前言 本文介绍一些正则中的常用名词以及对应概念,譬如字符组,捕获组.非捕获组.反向引用.转义和\s \b等 大纲 字符组 捕获组 反向引用 非捕获组 ..\s和\S \b \转义 字符组 []字符组表 ...

  3. 捕获分组和非捕获分组以及命名分组

    下面由一个例子引出非捕获组. 有两个金额:8899¥.显然,前一个是8899元的人民币,后一个是6688元的美元.我现在需要一个正则,要求提炼出它们的货币金额和货币种类.正则可以这写:(\\d)+([ ...

  4. 正则表达式 非捕获性分组

    非捕获性分组语法为(?:pattern),即将pattern部分组合成一个可统一操作的组合项,但不把这部分内容当作子匹配捕获,匹配的内容部进行编号也不存储在缓冲区中供以后使用.非捕获性分组方法在必须进 ...

  5. lambda捕获this_非捕获Lambda的实例

    lambda捕获this 大约一个月前,我在Java 8的lambda表达式框架下总结了Brian Goetz的观点 . 目前,我正在研究有关默认方法的文章,令我惊讶的是,我又回到了Java处理lam ...

  6. 非捕获Lambda的实例

    大约一个月前,我在Java 8的lambda表达式框架下总结了Brian Goetz的观点 . 目前,我正在研究有关默认方法的文章,令我惊讶的是,我又回到了Java处理lambda表达式的方式. 这两 ...

  7. 正则表达式的非捕获性分组

    非捕获性分组,通常由一对括号加上 ?: 加上子表达式组成,非捕获性分组不会创建反向引用,就好像没有括号一样.如下: var color = "#808080"; var outpu ...

  8. 正则表达式捕获分组和非捕获分组及用法

    正则表达式 (regular expression)是一个描述字符模式的对象. ECMAScript 的 RegExp 类 表示正则表达式,而 String 和 RegExp 都定义了使用正则表达式进 ...

  9. 正则基础之——非捕获组

    非捕获组:(?:Expression) 接触正则表达式不久的人,通常都会对非捕获比较迷惑,为什么要有非捕获组?作用是什么?应该在什么场景下使用? 说到非捕获组,首先要了解什么是捕获组,详细内容参考 正 ...

最新文章

  1. linux怎样优化桌面,简单优化设置Ubuntu 18.04系统的GNOME桌面
  2. nginx 子请求接收响应_Nginx详解其原理
  3. Homebrew安装不要改hosts了,直接用这个国内源才爽!
  4. 远期合约(Forwards/Forward Contract )
  5. ASP.NET+SQL创建存储过程
  6. JFreeChart(一)之架构
  7. 激活策略 查询_5个提问,详细介绍北极星指标的策略框架
  8. lrange是取出所有值并移除么_图解双指针 | LeetCode 27. 移除元素
  9. 千牛机器人回复词库_智能聊天机器人 ai机器人电销-
  10. Android仿人人客户端(v5.7.1)——采用ViewGroup做父容器,实现左侧滑动菜单(三)...
  11. linux目录跳转快捷方式——z武器
  12. 漆桂林:多模态知识图谱种类及其应用
  13. 西南农业大学成教学院有计算机专业吗,西南农业大学计算机应用与技巧网上功课及答案...
  14. python计算特征根以及特征向量
  15. 优动漫PAINT实用教程——创建自动动作提高效率
  16. ogg是什么文件?ogg怎么转mp3格式?
  17. Codeforces Gym 101086 M ACPC Headquarters : AASTMT (Stairway to Heaven)
  18. QT: 为自己的QT程序添加一个登录界面
  19. 我如何为我的第一个自由客户构建第一个React Native应用程序
  20. 【179期】这些最常用的Linux命令都不会,你怎么敢去面试?

热门文章

  1. 论文浅尝 | 一个模型解决所有问题:实体和事件的神经联合模型
  2. 在服务器上安装anaconda遇到的问题总结
  3. Android官方开发文档Training系列课程中文版:管理音频播放之控制APP的音量与播放
  4. BIO,NIO,AIO
  5. redis笔记_源码_简单动态字符串SDS
  6. python:更改pip源
  7. 剖析云平台中的“共享型数据库”
  8. DEDE无简略标题时显示完整标题
  9. jwplayer 消除logo
  10. SharePoint创建web application的时候报错