Regex Именованные группы в Java

Насколько я понимаю, пакет java.regex не поддерживает именованные группы (http://www.regular-expressions.info/named.html), так что кто-нибудь может указать мне на сторонняя библиотека, которая делает?

Я просмотрел jregex, но его последний выпуск был в 2002 году, и это не сработало для меня (по общему признанию, я только пытался кратко) под java5.

Ответ 1

(Обновить: Август 2011)

В качестве geofflane упоминается его ответ, Java 7 теперь поддерживает именованные группы.
tchrist указывает в комментарии, что поддержка ограничена.
Он детализирует ограничения в своем замечательном ответе Java Regex Helper"

Поддержка Java 7 regex с именем group была представлена ​​в сентябрь 2010 в блоге Oracle.

В официальном выпуске Java 7 конструкциями, поддерживающими названную группу захвата, являются:

  • (?<name>X) для определения имени именованной группы "
  • \k<name> для обратной ссылки названная группа" name "
  • ${name} для ссылки на захваченную группу в строке замены Matcher
  • Matcher.group(String name), чтобы вернуть захваченную входную подпоследовательность заданной" именованной группе ".

Другие альтернативы для pre-Java 7:


( Оригинальный ответ: январь 2009, со следующими двумя сломанными слотами)

Вы не можете ссылаться на именованную группу, если вы не указали свою собственную версию Regex...

Именно это Gorbush2 сделал в этом потоке.

Regex2

(ограниченная реализация, о чем еще раз отметили tchrist, поскольку она выглядит только для идентификаторов ASCII. tchrist указывает ограничение как:

может иметь только одну именованную группу для одного и того же имени (к которой вы не всегда имеете контроль!) и не можете использовать их для рекурсии в регулярном выражении.

Примечание. Примеры верных регулярных выражений можно найти в регулярных выражениях Perl и PCRE, как указано в Regexp Power, спецификации PCRE и Сопоставление строк со сбалансированными круглыми скобками)

Пример:

String

"TEST 123"

RegExp:

"(?<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

Да, но его грязный взлом классов солнца. Существует более простой способ:

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

named-regexp - это тонкая оболочка для стандартные регулярные выражения JDK реализации, с единственным назначение обработки названного захвата групп в стиле .net: (?...).

Он может использоваться с Java 5 и 6 (используются дженерики).

Java 7 будет обрабатывать именованный захват групп, поэтому этот проект не предназначен для продолжения.

Ответ 4

Какую проблему вы испытываете с jregex? Он работал хорошо для меня под java5 и java6.

Jregex делает работу хорошо (даже если последняя версия с 2002 года), если вы не хотите ждать javaSE 7.

Ответ 5

Для тех, кто работает с pre-java7, именованные группы поддерживаются joni (порт Java Oniguruma библиотека regexp). Документация разрежена, но она хорошо сработала для нас.
Бинарники доступны через Maven (http://repository.codehaus.org/org/jruby/joni/joni/).

Ответ 6

Немного старый вопрос, но я тоже нуждался в этом, и что приведенные выше предложения были неадекватными - и как таковые - сами разработали тонкую оболочку: https://github.com/hofmeister/MatchIt