这是我的理解,java。Regex包不支持命名组(http://www.regular-expressions.info/named.html),所以谁能告诉我一个第三方库,这样做?

我曾经研究过jregex,但它上一次发布是在2002年,它在java5下对我不起作用(诚然,我只是简单地尝试过)。


当前回答

(更新日期:2011年8月)

正如geofflane在他的回答中提到的,Java 7现在支持命名组。 Tchrist在评论中指出,这种支持是有限的。 他在他的回答“Java Regex Helper”中详细介绍了局限性。

Java 7正则表达式名为组支持,早在2010年9月就在Oracle的博客中出现了。

在Java 7的正式版本中,支持命名捕获组的构造如下:

(?<name>捕获文本)定义命名组"name" \k<name>反向引用命名组"name" ${name}引用Matcher替换字符串中的捕获组 匹配器。group(字符串名)返回给定“命名组”捕获的输入子序列。


java 7之前的其他替代方案有:

谷歌name -regex(见John Hardy的回答) Gábor Lipták提到(2012年11月),这个项目可能不活跃(有几个突出的bug),它的GitHub分支可以被考虑代替。 jregex(参见Brian Clozel的回答)


(原答案:2009年1月,后两个链接已断开)

您不能引用命名组,除非您编写了自己的Regex版本…

这正是Gorbush2在这篇文章中所做的。

Regex2

(tchrist再次指出,实现有限,因为它只查找ASCII标识符。Tchrist详述了限制如下:

每个相同的名称只能有一个命名组(您并不总是能够控制!),并且不能将它们用于正则表达式内递归。

注意:您可以在Perl和PCRE正则表达式中找到真正的正则表达式递归示例,如Regexp Power, PCRE规范和匹配带有平衡括号的字符串幻灯片中所述)

例子:

字符串:

"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;
                }

其他回答

对于运行java7之前版本的用户,joni (Oniguruma regexp库的Java端口)支持命名组。文档很少,但对我们来说效果很好。 二进制文件可以通过Maven (http://repository.codehaus.org/org/jruby/joni/joni/)获得。

(更新日期:2011年8月)

正如geofflane在他的回答中提到的,Java 7现在支持命名组。 Tchrist在评论中指出,这种支持是有限的。 他在他的回答“Java Regex Helper”中详细介绍了局限性。

Java 7正则表达式名为组支持,早在2010年9月就在Oracle的博客中出现了。

在Java 7的正式版本中,支持命名捕获组的构造如下:

(?<name>捕获文本)定义命名组"name" \k<name>反向引用命名组"name" ${name}引用Matcher替换字符串中的捕获组 匹配器。group(字符串名)返回给定“命名组”捕获的输入子序列。


java 7之前的其他替代方案有:

谷歌name -regex(见John Hardy的回答) Gábor Lipták提到(2012年11月),这个项目可能不活跃(有几个突出的bug),它的GitHub分支可以被考虑代替。 jregex(参见Brian Clozel的回答)


(原答案:2009年1月,后两个链接已断开)

您不能引用命名组,除非您编写了自己的Regex版本…

这正是Gorbush2在这篇文章中所做的。

Regex2

(tchrist再次指出,实现有限,因为它只查找ASCII标识符。Tchrist详述了限制如下:

每个相同的名称只能有一个命名组(您并不总是能够控制!),并且不能将它们用于正则表达式内递归。

注意:您可以在Perl和PCRE正则表达式中找到真正的正则表达式递归示例,如Regexp Power, PCRE规范和匹配带有平衡括号的字符串幻灯片中所述)

例子:

字符串:

"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;
                }

你用jregex会遇到什么问题? 它在java5和java6下工作得很好。

Jregex很好地完成了这项工作(即使上一个版本是2002年的),除非您想等待javaSE 7。

一个有点老的问题,但我发现自己也需要这个,上面的建议是不够的——因此,我自己开发了一个薄薄的包装:https://github.com/hofmeister/MatchIt

对于晚到的人:Java 7添加了命名组。匹配器。group(String groupName)文档。