Java中的正则表达式命名组
问题
据我所知,java.regex
包不支持命名组(http://www.regular-expressions.info/named.html)所以有人能指向我的第三方库吗?
我看了jregex但是它的最后一个版本是在2002年,它在java5下对我(不可否认我只是简单地试过)不起作用。
#1 热门回答(219 赞)
(更新:2011年8月)
Asgeofflanementions inhis answer,Java 7 now support named groups。
tchrist在评论中指出支持是有限的。
在他的伟大答案"Java Regex Helper"中说明其局限性
Java 7正则表达式命名组支持在Oracle的博客中于2002年9月的224861432发布。
在Java 7的官方发行版中,支持命名捕获组的构造是:
(?<name>捕获文本)定义命名组"name"\ k <name>以反向引用命名组"name"$ 以引用Matcher替换字符串中捕获的组Matcher.group(String name)通过给定的"命名组"返回捕获的输入子序列。
Java 7之前的其他替代方案:
- Google named-regex(请参阅John Hardy的回答)GáborLipták提到(2012年11月)该项目可能不活跃(有几个突出的错误),而且可以考虑使用它的GitHub fork。
- jregex(见Brian Clozel的回答)
(原文回答:Jan 2009,接下来的两个链接现已破]
你不能引用命名组,除非你编写自己的Regex版本...
那正是Gorbush2 did in this thread。
Regex2
(有限的实现,正如tchrist所指出的那样,因为它只查找ASCII标识符.tchrist将限制详述为:
只能在每个相同的名称上拥有一个命名组(你并不总是可以控制!)并且无法将它们用于正则表达式递归。
注意:你可以在Perl和PCRE正则表达式中找到真正的正则表达式递归示例,如Regexp Power,PCRE specs和Matching Strings with Balanced Parenthesesslide中所述)
例:
串:
"TEST 123"
正则表达式:
"(?<login>\\w+) (?<id>\\d+)"
访问
matcher.group(1) ==> TEST
matcher.group("login") ==> TEST
matcher.name(1) ==> login
更换
matcher.replaceAll("aaaaa_$1_sssss_$2____") ==> aaaaa_TEST_sssss_123____
matcher.replaceAll("aaaaa_${login}_sssss_${id}____") ==> aaaaa_TEST_sssss_123____
(摘自实施)
public final class Pattern
implements java.io.Serializable
{
[...]
/**
* Parses a group and returns the head node of a set of nodes that process
* the group. Sometimes a double return system is used where the tail is
* returned in root.
*/
private Node group0() {
boolean capturingGroup = false;
Node head = null;
Node tail = null;
int save = flags;
root = null;
int ch = next();
if (ch == '?') {
ch = skip();
switch (ch) {
case '<': // (?<xxx) look behind or group name
ch = read();
int start = cursor;
[...]
// test forGroupName
int startChar = ch;
while(ASCII.isWord(ch) && ch != '>') ch=read();
if(ch == '>'){
// valid group name
int len = cursor-start;
int[] newtemp = new int[2*(len) + 2];
//System.arraycopy(temp, start, newtemp, 0, len);
StringBuilder name = new StringBuilder();
for(int i = start; i< cursor; i++){
name.append((char)temp[i-1]);
}
// create Named group
head = createGroup(false);
((GroupTail)root).name = name.toString();
capturingGroup = true;
tail = root;
head.next = expr(tail);
break;
}
#2 热门回答(27 赞)
是的,但它太乱了太阳课。有一种更简单的方法:
http://code.google.com/p/named-regexp/> named-regexp是标准JDK正则表达式实现的瘦包装器,其唯一目的是以.net样式处理命名捕获组:(?...)。它可以与Java 5和6一起使用(使用泛型)。 Java 7将处理命名的捕获组,因此该项目并不意味着持续。
#3 热门回答(24 赞)
对于那些迟到的人:Java 7添加了命名组.Matcher.group(String groupName) documentation.