web-dev-qa-db-fra.com

Comment itérer sur une expression rationnelle

Disons que j'ai la chaîne suivante:

name1=gil;name2=orit;

Je veux trouver toutes les correspondances de name=value et m'assurer que toute la chaîne correspond au modèle.

Alors j'ai fait ce qui suit:

  1. Assurez-vous que tout le motif correspond à ce que je veux.

    Pattern p = Pattern.compile("^((\\w+)=(\\w+);)*$");
    Matcher m = p.matcher(line);
    if (!m.matches()) {
        return false;
    }
    
  2. Itérer sur le motif name=value

    Pattern p = Pattern.compile("(\\w+)=(\\w+);");
    Matcher m = p.matcher(line);
    while (m.find()) {
        map.put(m.group(1), m.group(2));
    }
    

Y a-t-il un moyen de faire cela avec une regex?

24
gilsilas

Vous pouvez valider et itérer des correspondances avec une regex en:

  • Assurez-vous qu'il n'y a pas de caractères incomparables entre les correspondances (par exemple, name1=x;;name2=y;) en mettant un \G au début de notre expression régulière, ce qui signifie "la fin de la correspondance précédente" .

  • Vérifier si nous avons atteint la fin de la chaîne lors de notre dernière correspondance en comparant la longueur de notre chaîne à Matcher.end() , qui retourne le décalage après le dernier caractère trouvé.

Quelque chose comme:

String line = "name1=gil;name2=orit;";
Pattern p = Pattern.compile("\\G(\\w+)=(\\w+);");
Matcher m = p.matcher(line);
int lastMatchPos = 0;
while (m.find()) {
   System.out.println(m.group(1));
   System.out.println(m.group(2));
   lastMatchPos = m.end();
}
if (lastMatchPos != line.length())
   System.out.println("Invalid string!");

Démo en direct .


Certaines langues peuvent vous permettre de parcourir les correspondances individuelles directement à partir de
^((\\w+)=(\\w+);)*$, mais je ne crois pas que vous puissiez le faire en Java.

29
Dukeling

Vous devez activer le mode multiligne pour que "^" et "$" fonctionnent correctement.

Pattern p = Pattern.compile("^(?:(\\w+)=(\\w+);)*$", Pattern.MULTILINE);
while (m.find()) {
    for (int i = 0; i < m.groupCount() - 2; i += 2) {
        map.put(m.group(i + 1), m.group(i + 2));
    }
}

Vous devez encore parcourir les groupes de correspondance pour chaque ligne et commenter le groupe externe en tant que groupe non capturant (?:...).

3
weaselflink
String example = "name1=gil;name2=orit;";
Pattern pattern = Pattern.compile("((name[0-9]+?=(.+?);))+?");
Matcher matcher = pattern.matcher(example);
// verifies full match
if (matcher.matches()) {
    System.out.println("Whole String matched: " + matcher.group());
    // resets matcher
    matcher.reset();
    // iterates over found
    while (matcher.find()) {
        System.out.println("\tFound: " + matcher.group(2));
        System.out.println("\t--> name is: " + matcher.group(3));
    }
}

Sortie: 

Whole String matched: name1=gil;name2=orit;
    Found: name1=gil;
    --> name is: gil
    Found: name2=orit;
    --> name is: orit
0
Mena