2009-09-04 20 views
14

Mam pewne skomplikowane wyrażenia regularne, które muszę skomentować dla czytelności i konserwacji. Specyfikacja Java jest dość lakoniczna i przez długi czas walczyłem o to. I wreszcie wpadła mi błąd i opublikować go jako odpowiedź ale byłbym wdzięczny za innych wskazówkach na utrzymanie regexesW tym komentarze w wyrażeniach regularnych Java

Jako przykład chcę komentować podskładniki (wzorców) w prosty parser nazwa:

String testTarget = "Waldorf T. Flywheel"; 
    String patternS = "([A-Za-z]+)\\s+([A-Z]\\.)?\\s+([A-Za-z]+)"; 
    Pattern pattern = Pattern.compile(patternS, Pattern.COMMENTS); 
    Assert.assertTrue(pattern.matcher(testTarget).matches()); 

EDYCJA: Byłbym wdzięczny także za przykłady formatu (? X).

EDYCJA: @ geowa4 ma dobrą sugestię, która pozwala uniknąć komentarzy osadzonych. Sinnce java i inni udostępnili osadzone komentarze, jakie są przypadki, w których są przydatne? (Myślę, że mam sprawę, ale chciałbym zobaczyć innych).

EDIT: Jak zaznaczono poniżej @mikej regex nie obsługuje opcjonalnego wstępnego dobrze i będzie lepiej jak:

 String patternS = "([A-Za-z]+)\\s+([A-Z]\\.\\s+)?([A-Za-z]+)"; 

ale to skończyć wydobywania miejsca w początkowej

Odpowiedz

21

Zobacz post przez Martin Fowler na ComposedRegex dla niektórych więcej pomysłów na temat poprawy regexp czytelność. Podsumowując, opowiada się za podzieleniem złożonego wyrażeń regularnych na mniejsze części, którym można nadać sensowne nazwy zmiennych. na przykład

String mandatoryName = "([A-Za-z]+)"; 
String mandatoryWhiteSpace = "\\s+"; 
String optionalInitial = "([A-Z]\\.)?"; 
String pattern = mandatoryName + mandatoryWhiteSpace + optionalInitial + 
    mandatoryWhiteSpace + mandatoryName; 
+0

Dzięki - jest to przydatne podejście. Wskazano także na inny pomysł używania języków specyficznych dla domeny do generowania wyrażeń regularnych (http://flimflan.com/blog/ReadableRegularExpressions.aspx). (W rzeczywistości to robię w mojej aplikacji, która ma skomplikowane kombinacje skompresowanych wyrażeń regularnych dla danych naukowych, ale to wykracza poza zakres tego pytania). –

+1

To jest bardzo czyste i schludne rozwiązanie. Chociaż opcjonalnyWhiteSpace powinien prawdopodobnie być obowiązkowyWhiteSpace? :) – crunchdog

+0

Dzięki crunchdog. Myślę, że to, co mnie zaskoczyło, jest faktycznym ograniczeniem we wzorze w tym, że jeśli mamy nazwę bez środkowego inicjału takiego jak Fred Bloggs, to potrzebujemy 2 spacji między imieniem i nazwiskiem, aby dopasować dwa \ \ s + we wzorze. Próbowałem rozwiązać ten problem, ale na razie zredagowałem odpowiedź, aby uzyskać wzór równoważny z tym z OP. – mikej

11

znalazłem Poniżej pracował:

 String pattern2S = 
      "([A-Za-z]+)  # mandatory firstName\n" + 
      "\\s+    # mandatory whitespace\n " + 
      "([A-Z]\\.)?  # optional initial\n" + 
      "\\s+    # whitespace\n " + 
      "([A-Za-z]+)  # mandatory lastName\n"; 

Kluczową sprawą było zawierać \ n znak nowej linii bezpośrednio w ciągu

15

Dlaczego nie można po prostu to zrobić:

String pattern2S = 
    "([A-Za-z]+)" + // mandatory firstName 
    "\\s+" +  // mandatory whitespace 
    ...; 

KONTYNUACJA:

Jeśli chcesz zachować komentarze ze wzorem i trzeba go odczytać z pliku właściwości, użyj tego:

pattern=\ 
#comment1\\n\ 
(A-z)\ 
#comment2\\n\ 
(0-9) 
+0

Dobra sugestia. Będzie to działać w wielu prostych przypadkach, ale chcę, aby wyrażenia regularne były niezależne od kodu, w którym są używane (np. W zewnętrznych plikach danych). Komentarze śródliniowe będą nadal widoczne. –

Powiązane problemy