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

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

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

6 ответов

Решение

(Обновление: август 2011 г.)

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

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

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

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

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


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

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

Именно это и сделал Gorbush2 в этой теме.

Regex2

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

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

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

Пример:

Строка:

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

Для людей, приходящих к этому поздно: Java 7 добавляет именованные группы. Matcher.group (String groupName) документация.

Да, но это грязное хакерство. Есть более простой способ:

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

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

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

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

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

Jregex хорошо справляется с этой задачей (даже если последняя версия 2002 года), если только вы не хотите ждать javaSE 7.

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

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

Другие вопросы по тегам