【问题标题】:Regex Named Groups in JavaJava中的正则表达式命名组
【发布时间】:2010-09-29 18:11:06
【问题描述】:

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

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

【问题讨论】:

  • 你的理解有误。 JDK7 处理命名组。
  • @tchrist 2009 年没有 JDK7。
  • 注意:这是discussed on Meta,12 年后。

标签: java regex


【解决方案1】:

更新2011 年 8 月

正如geofflanehis answer 中提到的那样,Java 7 now support named groups
tchrist 在评论中指出支持是有限的。
在他的精彩回答“Java Regex Helper”中详细说明了局限性

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

在 Java 7 的正式版本中,支持命名捕获组的结构是:

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

Java 7 之前的其他替代方案是:


原始答案2009 年 1 月,接下来的两个链接现已断开)

您不能引用命名组,除非您编写自己的正则表达式版本...

这正是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;
                }

【讨论】:

  • 上面的两个链接好像都坏了?
  • 这段代码有问题。它正在寻找 ASCII 标识符。这是错误的。它应该在标识符中查找 Java 允许的任何内容!
  • 仅供参考,因为你看起来很认真,有限的部分不是关于 ASCII 与 Unicode 名称,而是关于每个相同名称只能有一个命名组(你没有t 始终可以控制!)并且无法将它们用于正则表达式内递归。
  • @tchrist:感谢您的精确度(包括在内)。我还添加了一个链接,返回您关于“Java Regex helper”的出色答案(已投票)。
  • Java 中没有 Matcher 对象的 matcher.name(int index) 方法??
【解决方案2】:

是的,但是破解太阳课程很麻烦。有一个更简单的方法:

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

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

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

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

【讨论】:

  • 可惜不能在 GWT 中使用。
  • 查看这个项目的GitHub fork,它修复了原来的几个错误。它也托管在 Maven Central 中。
  • 请注意,Github 上的 tony19 fork 从 0.1.8 开始无法在 Android 上运行。
  • @RubberMallet,Android 特有的问题现在是 fixed,并将在 0.1.9 中出现。
【解决方案3】:

jregex 遇到了什么问题? 它在 java5 和 java6 下对我来说效果很好。

Jregex 做得很好(即使最后一个版本是 2002 年的),除非you want to wait for javaSE 7

【讨论】:

    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

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

      【讨论】:

      • 我对上面 Ryan 提到的 joni 选项非常感兴趣——你有任何使用命名捕获组的代码 sn-ps——我已经设法让基本匹配和搜索正常工作——但我看不到我将使用哪种方法来访问 groupNames 或使用组名获取捕获的值。
      【解决方案6】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-11-11
        • 1970-01-01
        • 2018-01-29
        • 2020-05-23
        • 2015-09-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多