2013-04-16 15 views
10

Chcę wygenerować wyrażenie regularne z ciągu zawierającego liczby, a następnie użyć go jako wzorca do wyszukiwania podobnych ciągów. Przykład:generowanie wyrażenia regularnego z ciągu znaków

String s = "Page 3 of 23" 

Jeśli zastąpić wszystkie cyfry \d

StringBuilder sb = new StringBuilder(); 
    for (int i = 0; i < s.length(); i++) { 
    char c = s.charAt(i); 
    if (Character.isDigit(c)) { 
     sb.append("\\d"); // backslash d 
    } else { 
     sb.append(c); 
     } 
    } 

    Pattern numberPattern = Pattern.compile(sb.toString()); 

// Pattern numberPattern = Pattern.compile("Page \d of \d\d"); 

I można wykorzystać, aby dopasować podobne łańcuchy (np "Page 7 of 47"). Mój problem polega na tym, że jeśli zrobię to naiwnie, niektóre metaznaki, takie jak (){}- itp., Nie zostaną usunięte. Czy istnieje biblioteka do tego lub wyczerpujący zestaw znaków dla wyrażeń regularnych, których muszę i nie wolno mi uciec? (Mogę spróbować wyodrębnić je z Javadocs, ale martwię się, że czegoś brakuje).

Alternatywnie istnieje biblioteka, która już to robi (na tym etapie nie chcę używać pełnego rozwiązania do przetwarzania języka naturalnego).

UWAGA: Edytowana odpowiedź @ dasblinkenlight działa teraz dla mnie!

+0

Oto odpowiedź na pytanie, które znaki pytanie, nie jestem świadomy żadnych bibliotek do generowania wyrażeń regularnych: http://stackoverflow.com/questions/399078/what-special-characters-must-be-escaped-in -regularne wyrażenia –

+0

@Evan dzięki. Interesuje mnie tylko Java, więc wygląda jak przydatny zasób. –

Odpowiedz

10

regexp biblioteki Java udostępnia tę funkcję:

String s = Pattern.quote(orig); 

W "cytowany" string będzie miał wszystkie swoje metaznaki uciekł. Najpierw uciec z łańcucha, a następnie przejść przez niego i zastąpić cyfry numerem \d, aby utworzyć wyrażenie regularne. Ponieważ biblioteka regex używa \Q i \E do cytowania, musisz zamknąć swoją część regex w odwrotnych cudzysłowach \E i \Q.

Jedną rzeczą, którą chciałbym zmienić w twojej implementacji jest algorytm zastępczy: zamiast zastępowania znaku po znaku, zamieniłbym cyfry w grupach. Pozwoli to na wyrażenie z Page 3 of 23 pasujących ciągów takich jak Page 13 of 23 i Page 6 of 8.

String p = Pattern.quote(orig).replaceAll("\\d+", "\\\\E\\\\d+\\\\Q"); 

To produce"\QPage \E\d+\Q of \E\d+\Q\E" bez względu na to, jaka strona cyfry i liczy się tam pierwotnie. Dane wyjściowe wymagają tylko jednego, nie dwóch ukośników w \d, ponieważ wynik jest podawany bezpośrednio do silnika regex, z pominięciem kompilatora Java.

+0

Fajnie, nie wiedziałem o tej metodzie. – toniedzwiedz

+0

@dasblinkenlight Świetnie! Zgadzam się, że mogę szukać powtarzających się cyfr, ale dla mnie jest też wartość heurystyczna z dokładnym zliczaniem cyfr. Mogę użyć obu podejść. –

+0

@ peter.murray.rust Zobacz ostatnią zmianę: liczba ukośników wymaganych do wykonania dwóch ukośników na wyjściu jest naprawdę niedorzeczna - razy dwa dla kompilatora i razy dwa dla biblioteki regex, łącznie osiem ukośników. – dasblinkenlight

Powiązane problemy