2013-07-31 16 views
103

Próbuję zrozumieć ten blok kodu. W pierwszym, czego szukamy w wyrażeniu?Grupy przechwytujące Java Regex

Rozumiem, że jest to dowolny znak (0 lub więcej razy *), po którym następuje dowolna liczba z zakresu od 0 do 9 (jeden lub więcej razy +), a następnie dowolny znak (0 lub więcej razy *).

Gdy ta jest wykonywana wynik to:

Found value: This order was placed for QT3000! OK? 
Found value: This order was placed for QT300 
Found value: 0 

Może ktoś proszę przejść przez to ze mną?

Jaka jest zaleta korzystania z funkcji Przechwytywanie grup?

import java.util.regex.Matcher; 
import java.util.regex.Pattern; 

public class RegexTut3 { 

    public static void main(String args[]) { 
     String line = "This order was placed for QT3000! OK?"; 
     String pattern = "(.*)(\\d+)(.*)"; 

     // Create a Pattern object 
     Pattern r = Pattern.compile(pattern); 

     // Now create matcher object. 
     Matcher m = r.matcher(line); 

     if (m.find()) { 
      System.out.println("Found value: " + m.group(0)); 
      System.out.println("Found value: " + m.group(1)); 
      System.out.println("Found value: " + m.group(2)); 
     } else { 
      System.out.println("NO MATCH"); 
     } 
    } 

} 
+0

Aby wstawić nową linię, umieść 2 spacje na końcu linii. Więcej o składni markdown: http://en.wikipedia.org/wiki/Markdown - Zobacz także: http: //stackoverflow.com/editing-help – assylias

Odpowiedz

158

Kwestia masz jest z rodzajem kwantyfikatorem. Używasz chciwy kwantyfikator w pierwszej grupie (indeks - indeks 0 reprezentuje cały Pattern), co oznacza, że ​​pasuje jak najwięcej jak to możliwe (i ponieważ jest to dowolny charakter, to będzie dopasuj jak najwięcej znaków, ponieważ są one w celu spełnienia warunku dla następnych grup).

Podsumowując, twoja pierwsza grupa .* pasuje do wszystkiego, o ile następna grupa \\d+ może pasować do czegoś (w tym przypadku do ostatniej cyfry).

Zgodnie z trzecią grupą będzie pasować do wszystkiego po ostatniej cyfrze.

Jeśli zmienisz go na niechętnie kwantyfikatora w 1 grupie, otrzymasz wynik Pewnie spodziewasz, to znaczy, że część.

Zanotuj znak zapytania w 1. grupie jako znak zapytania.

String line = "This order was placed for QT3000! OK?"; 
Pattern pattern = Pattern.compile("(.*?)(\\d+)(.*)"); 
Matcher matcher = pattern.matcher(line); 
while (matcher.find()) { 
    System.out.println("group 1: " + matcher.group(1)); 
    System.out.println("group 2: " + matcher.group(2)); 
    System.out.println("group 3: " + matcher.group(3)); 
} 

wyjściowa:

group 1: This order was placed for QT 
group 2: 3000 
group 3: ! OK? 

Więcej informacji na Java Patternhere.

Na koniec grupy przechwytywania są ograniczone za pomocą nawiasów okrągłych i stanowią bardzo użyteczny sposób użycia odnośników (między innymi), po tym, jak Pattern zostanie dopasowany do danych wejściowych.

W języku Java 6 grup można odwoływać się wyłącznie według ich kolejności (uważaj na zagnieżdżone grupy i subtelność zamawiania).

W języku Java 7 jest to znacznie łatwiejsze, ponieważ można używać nazwanych grup.

+0

Dzięki! Czy grupa przyczyn 2 jest przechowywana 0, ponieważ cała linia została pochłonięta przez chciwy kwantyfikator, który następnie wycofał się, dopóki nie wszedł w kontakt z jedną lub więcej liczb. 0 spełniło to, więc wyrażenie się udało. Uważam, że trzecia grupa jest myląca, czy ten chciwy kwantyfikator również pochłania całą linię, ale cofa się, dopóki nie znajdzie jednej lub więcej liczb (\\ d +), które powinny ją poprzedzić? – Xivilai

+0

@Xivilai pozwól mi dostroić moje wyjaśnienie w mojej odpowiedzi, tylko na sekundę. – Mena

+0

To dobre wyjaśnienie. Niechętny zaczyna się od lewej i zajmuje minimum, natomiast w przypadku chciwości zajmie to jak najwięcej (zaczynając od prawej), zatrzymując się przed ostatnią cyfrą, aby spełnić ten warunek. Trzecia grupa zajmuje resztę. – Xivilai

3

Twoje zrozumienie jest prawidłowe. Jednak jeśli przejdziemy przez:

  • (.*) połknie cały ciąg;
  • będzie musiał oddać znaki, aby (\\d+) był satistifed (dlatego 0 jest przechwytywane, a nie 3000);
  • ostatni (.*) następnie przechwyci resztę.

Nie jestem jednak pewien, jaka była pierwotna intencja autora.

1

Od doc:

Capturing groups</a> are indexed from left 
* to right, starting at one. Group zero denotes the entire pattern, so 
* the expression m.group(0) is equivalent to m.group(). 

więc uchwycić grupa 0 wysłać całą linię.

11

To jest całkowicie OK.

  1. Pierwsza grupa (m.group(0)) zawsze oddaje cały obszar, który jest pokryty przez wyrażenie regularne. W tym przypadku jest to cały ciąg.
  2. Wyrażenia regularne są domyślnie chciwe, co oznacza, że ​​pierwsza grupa przechwytuje jak najwięcej, bez naruszania wyrażenia regularnego. (.*)(\\d+) (pierwsza część twojego regex) obejmuje ...QT300 w pierwszej grupie i 0 w drugiej.
  3. Możesz szybko to naprawić, czyniąc pierwszą grupę nie chciwą: zmień (.*) na (.*?).

Aby uzyskać więcej informacji na temat zachłanny vs. leniwa, sprawdź this site.

Powiązane problemy