2012-12-07 12 views
7

AKTUALIZACJA: Dzięki za wszystkie świetne odpowiedzi! Próbowałem wielu różnych wzorów regex, ale nie rozumiałem, dlaczego m.matches() nie robi tego, co moim zdaniem powinno być. Kiedy przełączyłem się na m.find(), a także dostosowując wzór regex, udało mi się gdzieś dostać.Grupa wzorów/Matchera() w celu uzyskania podciągu w języku Java?


Chciałbym pasuje do wzorca w łańcuchu Java, a następnie wyodrębnić część dopasowaną za pomocą regex (jak $ & operatora Perl).

To jest mój łańcuch źródłowy "s": DTSTART;TZID=America/Mexico_City:20121125T153000 Chcę wyodrębnić część "America/Mexico_City".

Pomyślałem, że mogę użyć Pattern i Matcher, a następnie wyodrębnić używając m.group(), ale to nie działa tak, jak się spodziewałem. Próbowałem małpować z różnymi ciągami regex i jedyną rzeczą, która wydaje się trafiać na m.matches() jest ".*TZID.*", co jest bezcelowe, ponieważ po prostu zwraca cały ciąg. Czy ktoś mógłby mnie oświecić?

Pattern p = Pattern.compile ("TZID*:"); // <- change to "TZID=([^:]*):" 
Matcher m = p.matcher (s); 
if (m.matches()) // <- change to m.find() 
    Log.d (TAG, "looking at " + m.group()); // <- change to m.group(1) 
+0

Wygląda na linii z pliku iCS (iCal) - dlaczego nie używacie http://ical4j.sourceforge.net/ lub odpowiednik? – jrtc27

+0

Rzeczywiście. Zacząłem od ical4j, ale zostało ono rzucone z błędem podczas analizowania pliku ics, więc porzuciłem go. Mogę spróbować ponownie, jeśli potrzebuję więcej funkcji niż tylko wyodrębnianie linii DTSTART. – wufoo

Odpowiedz

7

użyć m.match() że próbuje dopasować cały ciąg, jeśli będziesz korzystać m.find(), to będzie szukać meczu wewnątrz, także ja nieco poprawić swoją regexp wykluczyć TZID prefiks za pomocą zerowej szerokości wyglądać za:

 Pattern p = Pattern.compile("(?<=TZID=)[^:]+"); // 
    Matcher m = p.matcher ("DTSTART;TZID=America/Mexico_City:20121125T153000"); 
    if (m.find()) { 
     System.out.println(m.group()); 
    } 
2

Brakuje kropki przed gwiazdką. Twoje wyrażenie będzie pasować do dowolnej liczby wielkich liter D s.

Pattern p = Pattern.compile ("TZID[^:]*:"); 

Należy również dodać przechwytywania grupę chyba że chcesz, aby uchwycić wszystko, łącznie z "TZID" i ":"

Pattern p = Pattern.compile ("TZID=([^:]*):"); 

Wreszcie, należy użyć odpowiedniego API, aby wyszukać ciąg, raczej niż próba dopasowania ciągu w całości.

Pattern p = Pattern.compile("TZID=([^:]*):"); 
Matcher m = p.matcher("DTSTART;TZID=America/Mexico_City:20121125T153000"); 
if (m.find()) { 
    System.out.println(m.group(1)); 
} 

Ten prints

America/Mexico_City 
2

Używasz złego wzorca, spróbuj tego:

Pattern p = Pattern.compile(".*?TZID=([^:]+):.*"); 
Matcher m = p.matcher (s); 
if (m.matches()) 
    Log.d (TAG, "looking at " + m.group(1)); 

.*? dopasuje coś na początku aż do TZID=, następnie TZID= dopasuje i grupa rozpocznie i dopasuje wszystko do :, grupa zostanie zamknięta tutaj, a następnie : pasuje i .* będzie pasował do reszty łańcucha, teraz można dostać to, czego potrzebujesz w group(1)

+0

Usunąłem prawie identyczną odpowiedź na twoją. Miałeś nieco lepsze wyrażenie regularne. – mikeslattery

6

To powinno działać ładnie:

Pattern p = Pattern.compile("TZID=(.*?):"); 
Matcher m = p.matcher(s); 
if (m.find()) { 
    String zone = m.group(1); // group count is 1-based 
    . . . 
} 

Alternatywą regex jest "TZID=([^:]*)". Nie jestem pewien, który jest szybszy.

1

Dlaczego nie wystarczy użyć podzielone jak:

String origStr = "DTSTART;TZID=America/Mexico_City:20121125T153000"; 
    String str = origStr.split(":")[0].split("=")[1]; 
+0

Bardzo eleganckie rozwiązanie. Dzięki – wufoo

Powiązane problemy