205 votes

Groupes de capture Java Regex

J'essaie de comprendre ce bloc de code. Dans le premier, qu'est-ce qu'on cherche dans l'expression ?

D'après ce que j'ai compris, il s'agit de n'importe quel caractère (0 ou plusieurs fois *) suivi de n'importe quel nombre entre 0 et 9 (une ou plusieurs fois +) suivi de n'importe quel caractère (0 ou plusieurs fois *).

Lorsque cette opération est exécutée, le résultat est le suivant :

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

Quelqu'un pourrait-il examiner cette question avec moi ?

Quel est l'avantage d'utiliser les groupes de capture ?

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

}

286voto

Mena Points 12283

Le problème que vous rencontrez est lié au type de quantificateur. Vous utilisez un gourmand quantificateur dans votre premier groupe (indice 1 - l'indice 0 représente l'ensemble Pattern ), ce qui signifie qu'il correspondra autant que possible (et comme il s'agit de tout le caractère, il correspondra à autant de personnages qu'il y en a afin de remplir la condition pour les groupes suivants).

En bref, votre 1er groupe .* correspond à n'importe quoi tant que le groupe suivant \\d+ peut correspondre à quelque chose (dans ce cas, le dernier chiffre).

Pour le troisième groupe, il correspondra à tout ce qui se trouve après le dernier chiffre.

Si vous le changez en réticent quantificateur dans votre 1er groupe, vous obtiendrez le résultat que vous attendez, je suppose, c'est-à-dire le 3000 partie.

Notez le point d'interrogation dans le 1er groupe.

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

Sortie :

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

Plus d'informations sur Java Pattern ici .

Enfin, les groupes de capture sont délimités par des parenthèses rondes, et fournissent un moyen très utile d'utiliser les références arrière (entre autres choses), une fois que votre fichier Pattern est adapté à l'entrée.

En Java 6, les groupes ne peuvent être référencés que par leur ordre (attention aux groupes imbriqués et à la subtilité de l'ordre).

Dans Java 7, c'est beaucoup plus facile, car vous pouvez utiliser des groupes nommés.

19voto

f1sh Points 2242

C'est tout à fait normal.

  1. Le premier groupe ( m.group(0) ) saisit toujours l'ensemble de la zone couverte par votre expression régulière . Dans ce cas, il s'agit de la chaîne entière.
  2. Les expressions régulières sont gourmandes par défaut, ce qui signifie que le premier groupe capture autant que possible sans violer la regex. Le site (.*)(\\d+) (la première partie de votre regex) couvre le ...QT300 dans le premier groupe et le 0 dans la seconde.
  3. Vous pouvez rapidement résoudre ce problème en rendant le premier groupe non gourmand : changez (.*) a (.*?) .

Pour plus d'informations sur l'avarice et la paresse, voir ce site.

6voto

fge Points 40850

Votre compréhension est correcte. Cependant, si nous marchons à travers :

  • (.*) va avaler toute la chaîne ;
  • il devra rendre des caractères pour que (\\d+) est satisfaite (c'est pourquoi 0 est capturé, et non 3000 ) ;
  • le dernier (.*) capturera ensuite le reste.

Je ne suis cependant pas sûr de l'intention initiale de l'auteur.

5voto

Michael Laffargue Points 5190

Du 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().

Donc le groupe de capture 0 envoie la ligne entière.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X