Java 正则表达式之捕获组

Java 正则表达式之捕获组

1. Java 正则表达式基础
2. Java 正则表达式之捕获组

一、概述

1.1 什么是捕获组

捕获组就是把正则表达式中子表达式匹配的内容,保存到内存中以数字编号或显式命名的组里,方便后面引用。当然,这种引用既可以是在正则表达式内部,也可以是在正则表达式外部。

捕获组有两种形式,一种是普通捕获组,另一种是命名捕获组,通常所说的捕获组指的是普通捕获组。语法如下:

普通捕获组:(Expression)
命名捕获组:(?<name>Expression)

普通捕获组在大多数支持正则表达式的语言或工具中都是支持的,而命名捕获组目前只有 .NET、PHP、Python 等部分语言支持,Java 7.0 中提供对这一特性的支持。

另外需要说明的一点是,除(Expression)和(?Expression)语法外,其它的(?...)语法都不是捕获组。

1.2 捕获组编号规则

编号规则指的是以数字为捕获组进行编号的规则,在普通捕获组或命名捕获组单独出现的正则表达式中,编号规则比较清晰,在普通捕获组与命名捕获组混合出现的正则表达式中,捕获组的编号规则稍显复杂。

在展开讨论之前,需要说明的是,编号为0的捕获组,指的是正则表达式整体,这一规则在支持捕获组的语言中,基本上都是适用的。下面对其它编号规则逐一展开讨论。

1.2.1 普通捕获组编号规则

如果没有显式为捕获组命名,即没有使用命名捕获组,那么需要按数字顺序来访问所有捕获组。在只有普通捕获组的情况下,捕获组的编号是按照“(”出现的顺序,从左到右,从 1 开始进行编号的 。

正则表达式:(\d{4})-(\d{2}-(\d\d))

上面的正则表达式可以用来匹配格式为 yyyy-MM-dd 的日期,为了在下表中得以区分,月和日分别采用了 \d{2} 和 \d\d 这两种写法。

用以上正则表达式匹配字符串:2008-12-31,匹配结果为:

编号 命名 捕获组 匹配内容
0 (\d{4})-(\d{2}-(\d\d)) 2008-12-31
1 (\d{4}) 2008
2 (\d{2}-(\d\d)) 12-31
3 (\d\d) 31

1.2.2?命名捕获组编号规则

命名捕获组通过显式命名,可以通过组名方便的访问到指定的组,而不需要去一个个的数编号,同时避免了在正则表达式扩展过程中,捕获组的增加或减少对引用结果导致的不可控。

不过容易忽略的是,命名捕获组也参与了编号的,在只有命名捕获组的情况下,捕获组的编号也是按照“(”出现的顺序,从左到右,从 1 开始进行编号的 。

正则表达式:(?<year>\d{4})-(?<date>\d{2}-(?<day>\d\d))

用以上正则表达式匹配字符串:2008-12-31

匹配结果为:

编号 命名 捕获组 匹配内容
0 (?<year>\d{4})-(?<date>\d{2}-(?<day>\d\d)) 2008-12-31
1 year (?<year>\d{4}) 2008
2 date (?<date>\d{2}-(?<day>\d\d)) 12-31
3 day (?<day>\d\d) 31

1.2.3 普通捕获组与命名捕获组混合编号规则

当一个正则表达式中,普通捕获组与命名捕获组混合出现时,捕获组的编号规则稍显复杂。对于其中的命名捕获组,随时都可以通过组名进行访问,而对于普通捕获组,则只能通过确定其编号后进行访问。

混合方式的捕获组编号,首先按照普通捕获组中“(”出现的先后顺序,从左到右,从1开始进行编号,当普通捕获组编号完成后,再按命名捕获组中“(”出现的先后顺序,从左到右,接着普通捕获组的编号值继续进行编号。

也就是先忽略命名捕获组,对普通捕获组进行编号,当普通捕获组完成编号后,再对命名捕获组进行编号。

正则表达式:(\d{4})-(?<date>\d{2}-(\d\d))
?编号 命名 捕获组 匹配内容
0 (\d{4})-(?<date>\d{2}-(\d\d)) 2008-12-31
1 (\d{4}) 2008
2 date (?<date>\d{2}-(\d\d)) 12-31
3 (\d\d) 31

二、捕获组的引用

正则表达式中,对前面捕获组捕获的内容进行引用,称为反向引用;

2.1 反向引用

捕获组捕获到的内容,不仅可以在正则表达式外部通过程序进行引用,也可以在正则表达式内部进行引用,这种引用方式就是反向引用。反向引用的作用通常是用来查找或限定重复,限定指定标识配对出现等等。

对于普通捕获组和命名捕获组的引用,语法如下:

  1. 普通捕获组反向引用:\k,通常简写为\number
  2. 命名捕获组反向引用:\k或者\k‘name‘

普通捕获组反向引用中 number 是十进制的数字,即捕获组的编号;命名捕获组反向引用中的name为命名捕获组的组名。

三、Java 中使用捕获组

在 Spring Cloud Zuul 中使用网关时,当 serviceId: serviceId-v1 时可自动映射为 v1/serviceId 路径

public PatternServiceRouteMapper serviceRouteMapper() {
    return new PatternServiceRouteMapper(
        "(?<name>^.+)-(?<version>v.+$)", "${version}/${name}");
}

其实现的原理如下:

public void testRegexGroup {
    String serviceId = "serviceId-v1";

    Pattern servicePattern = Pattern.compile("(?<name>.+)-(?<version>v.+$)");
    Matcher matcher = servicePattern.matcher(serviceId);
    String route = matcher.replaceFirst("${version}/${name}");
    Assert.assertEquals("v1/serviceId", route);
}

参考:

  1. 《JAVA 正则表达式》:https://www.cnblogs.com/xyou/p/7427779.html
  2. 《正则基础之——捕获组(capture group)》:https://blog.csdn.net/lxcnn/article/details/4146148


每天用心记录一点点。内容也许不重要,但习惯很重要!

原文地址:https://www.cnblogs.com/binarylei/p/10626470.html

时间: 2024-08-28 23:54:41

Java 正则表达式之捕获组的相关文章

Java Matcher类 replaceAll 捕获组使用及使用符号$引用捕获组

Java Matcher类 replaceAll 捕获组使用及使用符号$引用捕获组 最近看了一段解析URL以判断支付方式是在线支付还是具体哪个网银或支付宝的代码.如下 private String[] getAction(String url){ String action = null; String pluginid = null; String pattern = "/(\\w+)_(\\w+)_(\\w+).html(.*)"; Pattern p = Pattern.comp

php 正则表达式捕获组与非捕获组

熟练掌握正则表达式是每个程序员的基础要求,对于每个初学者来说会被正则表达式一连串字符弄得头晕眼花.博主便会如此,一直对正则表达式有种莫名的恐惧.近来看到另一位博友写的 <php正则表达式>一文获益良多,对其通配符以及捕获数据两个章节颇感兴趣.这两个章节正好涉及到的是正则表达式的捕获组与非捕获组的知识,因而本文来细细探讨下这部分知识. 我们知道,在正则表达式下(x) 表示匹配'x'并记录匹配的值.这只是比较通俗的说法,甚至说这是不严谨的说法,只有()捕获组形式才会记录匹配的值.非捕获组则只匹配,

Java正则表达式中的捕获组的概念(转)

要弄清这三个方法,首先要弄清Java正则表达式中的捕获组的概念.捕获组也就是Pattern中以括号对“()”分割出的子Pattern.至于为什么要用捕获组呢,主要是为了能找出在一次匹配中你更关心的部分.捕获组可以通过从左到右计算其开括号来编号.例如,在表达式 "(x)(y\\w*)(z)" 中,存在三个这样的组:  1.  x2.  y\\w*3.  z组零始终代表整个表达式.之所以这样命名捕获组是因为在匹配中,保存了与这些组匹配的输入序列的每个子序列.捕获的子序列稍后可以通过 Bac

深入入门正则表达式(java) - 命名捕获

深入入门正则表达式(java) - 引言 深入入门正则表达式(java) - 1 - 入门基础深入入门正则表达式(java) - 2 - 基本实例 深入入门正则表达式(java) - 3 - 正则在java中的使用 深入入门正则表达式(java) - 匹配原理 - 1 - 引擎分类与普适原则 深入入门正则表达式(java) - 匹配原理 - 2 - 回溯 深入入门正则表达式(java) - 命名捕获 很多正则引擎都支持命名分组,java是在java7中才引入这个特性,语法与.Net类似(.Net

JAVA正则表达式高级用法(分组与捕获)

正则表达式在字符串处理中经常使用,关于正则简单的用法相信有一点程序基础的人都懂得一些,这里就不介绍简单基础了.这里主要讲解一下在JAVA中实现了的正则的高级用法-分组与捕获.对于要重复单个字符,非常简单,直接在字符后卖弄加上限定符即可,例如 a+ 表示匹配1个或一个以上的a,a?表示匹配0个或1个a.这些限定符如下所示: X ?     X ,一次或一次也没有X *     X ,零次或多次X +     X ,一次或多次X { n }     X ,恰好 n 次X { n ,}     X ,

正则表达式 1. 分组提取/非捕获组

https://www.zybuluo.com/Zjmainstay/note/709093 1. 分组提取/非捕获组 分组,是正则里一个非常重要的概念,我们需要针对某个区域提取数据,往往需要依赖分组.而分组,其实就是正则里()括住的部分. (1.1)分组提取 需求:在分组1中匹配meta中author属性的值源串:<meta author="Zjmainstay" />another author="Zjmainstay too"预期:分组1得到Zjm

JAVA正则表达式:Pattern类与Matcher类详解(转)

java.util.regex是一个用正则表达式所订制的模式来对字符串进行匹配工作的类库包.它包括两个类:Pattern和Matcher Pattern 一个Pattern是一个正则表达式经编译后的表现模式. Matcher 一个Matcher对象是一个状态机器,它依据Pattern对象做为匹配模式对字符串展开匹配检查. 首先一个Pattern实例订制了一个所用语法与PERL的类似的正则表达式经编译后的模式,然后一个Matcher实例在这个给定的Pattern实例的模式控制下进行字符串的匹配工作

JAVA 正则表达式 (超详细)

(PS:这篇文章为转载,我不喜欢转载的但我觉得这篇文章实在是超赞了,就转了过来,这篇可以说是学习JAVA正则表达的必读篇.作者是个正真有功力的人,阅读愉快) 在Sun的JavaJDK 1.40版本中,Java自带了支持正则表达式的包,本文就抛砖引玉地介绍了如何使用java.util.regex包. 可粗略估计一下,除了偶尔用Linux的外,其他Linu x用户都会遇到正则表达式.正则表达式是个极端强大工具,而且在字符串模式-匹配和字符串模式-替换方面富有弹性.在Unix世界里,正则表达式几乎没有

java正则表达式

在做 Crawler的时候,本来是准备用正则的,但是看jsoup很好用,就没有学,刚刚在做古诗提取的时候,又要用到正则表达式,还是学了算了. 说明: 文章重点参考的http://www.cnblogs.com/ggjucheng/p/3423731.html,加上自己有一点理解. 正则表达式的语法可以参考: http://www.runoob.com/regexp/regexp-syntax.html java正则表达式主要是关于java.util.regex中的两个类: 1.Pattern:正