Java中的正则表达式命名组

时间:2009-01-06 05:45:36

标签: java regex

我的理解是java.regex包不支持命名组(http://www.regular-expressions.info/named.html)所以有人能指向我的第三方库吗?

我看过jregex,但它的最后一个版本是在2002年,它在java5下对我(不可否认,我只是简单地尝试过)不起作用。

6 个答案:

答案 0 :(得分:240)

更新 2011年8月

geofflanehis answer中提及Java 7 now support named groups tchrist在评论中指出支持是有限的 他详细说明了他的答案“Java Regex Helper

的局限性

Java 7正则表达式命名组支持在September 2010 in Oracle's blog中提供。

在Java 7的官方发行版中,支持命名捕获组的构造是:

  
      
  • (?<name>capturing text)定义命名组“name”
  •   
  • \k<name>反向引用命名组“name”
  •   
  • ${name}引用Matcher的替换字符串中的捕获组
  •   
  • Matcher.group(String name)以给定的“命名组”返回捕获的输入子序列。
  •   

Java 7之前的其他替代方案


原始回答 2009年1月,现在已经破了下两个链接)

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

这正是Gorbush2 did in this thread

Regex2

(有限的实现,正如tchrist所指出的那样,因为它只查找ASCII标识符.tchrist将限制详述为:

  

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

注意:您可以在Perl和PCRE正则表达式中找到真正的正则表达式递归示例,如Regexp PowerPCRE specsMatching Strings with Balanced Parentheses幻灯片中所述

示例:

字符串:

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

答案 1 :(得分:27)

是的,但它太乱了太阳课。有一种更简单的方法:

http://code.google.com/p/named-regexp/

  

named-regexp是一个瘦的包装器   标准的JDK正则表达式   实施,单一   处理命名捕获的目的   .net样式的组:   (?...)。

     

它可以与Java 5和6一起使用   (使用泛型)。

     

Java 7将处理命名捕获   小组,所以这个项目并不意味着   持续。

答案 2 :(得分:25)

对于那些迟到的人:Java 7添加了命名组。 Matcher.group(String groupName) documentation.

答案 3 :(得分:2)

jregex会遇到什么问题? 在java 5和java 6下,它对我很有用。

正则表达能很好地完成工作(即使最后一个版本是2002年),除非you want to wait for javaSE 7

答案 4 :(得分:2)

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

答案 5 :(得分:1)

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