Nazwane grupy Regex w Javie


173

Rozumiem, że java.regexpakiet nie obsługuje nazwanych grup ( http://www.regular-expressions.info/named.html ), więc czy ktoś może wskazać mi bibliotekę innej firmy, która ją obsługuje?

Patrzyłem na jregex, ale jego ostatnie wydanie było w 2002 roku i nie działało dla mnie (wprawdzie próbowałem tylko przez chwilę) pod java5.


3
Twoje rozumienie jest błędne. JDK7 obsługuje nazwane grupy.
tchrist

2
@tchrist W 2009 roku nie było JDK7.
Alex78191

Odpowiedzi:


275

( Aktualizacja : sierpień 2011 )

Jak geofflane wspomina w swojej odpowiedzi , Java 7 obsługuje teraz nazwane grupy .
tchrist zwraca uwagę w komentarzu, że wsparcie jest ograniczone.
On szczegóły ograniczeń w swej wielkiej odpowiedź „ Java Regex Helper

Obsługa grup o nazwie regex Java 7 została zaprezentowana we wrześniu 2010 roku na blogu Oracle .

W oficjalnym wydaniu Java 7 konstrukcje obsługujące nazwaną grupę przechwytującą to:

  • (?<name>capturing text) definiowanie nazwanej grupy „nazwa”
  • \k<name> odwoływać się do nazwanej grupy „nazwa”
  • ${name} do odniesienia do przechwyconej grupy w łańcuchu zastępczym Matchera
  • Matcher.group(String name) zwraca przechwycony podciąg wejściowy przez daną „nazwaną grupę”.

Inne alternatywy dla wersji przed Java 7 to:


( Oryginalna odpowiedź : styczeń 2009 r. , Kolejne dwa linki są teraz uszkodzone)

Nie możesz odwoływać się do nazwanej grupy, chyba że zakodujesz własną wersję Regex ...

Dokładnie to zrobił Gorbush2 w tym wątku .

Regex2

(ograniczona implementacja, jak wskazał ponownie tchrist , ponieważ szuka tylko identyfikatorów ASCII. tchrist opisuje to ograniczenie jako:

możliwość posiadania tylko jednej nazwanej grupy dla tej samej nazwy (nad którą nie zawsze masz kontrolę!) i niemożność użycia ich do rekurencji w wyrażeniu regularnym.

Uwaga: przykłady prawdziwej rekurencji wyrażeń regularnych można znaleźć w wyrażeniach regularnych Perla i PCRE, jak wspomniano na slajdzie Regexp Power , PCRE specs and Matching Strings with Balanced Nawiasy

Przykład:

Strunowy:

"TEST 123"

RegExp:

"(?<login>\\w+) (?<id>\\d+)"

Dostęp

matcher.group(1) ==> TEST
matcher.group("login") ==> TEST
matcher.name(1) ==> login

Zastąpić

matcher.replaceAll("aaaaa_$1_sssss_$2____") ==> aaaaa_TEST_sssss_123____
matcher.replaceAll("aaaaa_${login}_sssss_${id}____") ==> aaaaa_TEST_sssss_123____ 

(wyciąg z realizacji)

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

oba powyższe linki wydają się być uszkodzone?
Jonas

Ten kod zawiera błędy. Szuka identyfikatorów ASCII. To jest źle. Powinien szukać wszystkiego, na co Java zezwala w identyfikatorze !!
tchrist

1
Po prostu do Twojej wiadomości, ponieważ wydajesz się tak sumienny, ograniczona część nie dotyczy tak wielu nazw ASCII vs Unicode, ponieważ chodzi tylko o możliwość posiadania jednej nazwanej grupy dla tej samej nazwy (nad którą nie zawsze masz kontrolę!) I niemożność użycia ich do rekurencji w wyrażeniu regularnym.
tchrist

@tchrist: dziękuję za tę precyzję (w zestawie). Dodałem również link z powrotem do Twojej znakomitej odpowiedzi na temat „Pomocnika Java Regex” (głos za pozytywnym).
VonC

Nie ma metody matcher.name (int index) dla obiektu Matcher w Javie?
ot0


27

Tak, ale to niechlujne hakowanie zajęć ze słońca. Jest prostszy sposób:

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

named-regexp jest cienkim opakowaniem dla standardowej implementacji wyrażeń regularnych JDK, którego jedynym celem jest obsługa nazwanych grup przechwytywania w stylu .net: (? ...).

Może być używany z Javą 5 i 6 (używane są generyczne).

Java 7 będzie obsługiwać nazwane grupy przechwytywania, więc ten projekt nie jest trwały.


1
Szkoda, że ​​nie można tego używać z poziomu GWT.
Sakuraba,

4
Sprawdź rozwidlenie GitHub tego projektu, które naprawia kilka błędów z oryginału. Jest również hostowany w Maven Central.
tony19

1
Tylko słowo ostrzeżenia w moim przypadku, widelec tony19 na Github nie działa na Androidzie od 0.1.8.
Chuck D

2
@RubberMallet, Problem specyficzny dla Androida został już naprawiony i będzie w wersji 0.1.9.
tony19


2

W przypadku użytkowników korzystających z wersji starszej niż java7, nazwane grupy są obsługiwane przez joni (port Java biblioteki regexp Oniguruma ). Dokumentacja jest skromna, ale nam się udało.
Pliki binarne są dostępne za pośrednictwem Maven ( http://repository.codehaus.org/org/jruby/joni/joni/ ).


Jestem bardzo zainteresowany opcją joni, o której wspomniał Ryan powyżej - czy masz jakieś fragmenty kodu używające nazwanych grup przechwytywania - udało mi się uzyskać podstawowe dopasowywanie i wyszukiwanie do prawidłowego działania - ale nie widzę, której metody użyłbym do uzyskać dostęp do groupNames lub uzyskać wartość przechwytywania przy użyciu nazwy grupy.
malsmith

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.