194 votes

Créer un tableau de correspondances regex

En Java, j'essaie de renvoyer toutes les correspondances d'expressions rationnelles dans un tableau, mais il semble que l'on puisse seulement vérifier si le motif correspond à quelque chose ou non (booléen).

Comment puis-je utiliser une correspondance regex pour former un tableau de toutes les chaînes correspondant à une expression regex dans une chaîne donnée ?

3 votes

Bonne question. L'information que vous cherchez devrait faire partie des documents Java sur Regex et Matcher. Malheureusement, ce n'est pas le cas.

4 votes

C'est vraiment dommage. Cette fonctionnalité semble exister d'emblée dans presque tous les autres langages (qui prennent en charge les expressions régulières).

313voto

Mike Samuel Points 54712

( Réponse de 4castle est meilleure que celle ci-dessous si vous pouvez supposer que Java >= 9)

Vous devez créer un matcher et l'utiliser pour trouver des correspondances de manière itérative.

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

 ...

 List<String> allMatches = new ArrayList<String>();
 Matcher m = Pattern.compile("your regular expression here")
     .matcher(yourStringHere);
 while (m.find()) {
   allMatches.add(m.group());
 }

Après ça, allMatches contient les correspondances, et vous pouvez utiliser allMatches.toArray(new String[0]) pour obtenir un tableau si vous en avez vraiment besoin.


Vous pouvez également utiliser MatchResult pour écrire des fonctions d'aide pour boucler sur les correspondances depuis Matcher.toMatchResult() renvoie un instantané de l'état actuel du groupe.

Par exemple, vous pouvez écrire un itérateur paresseux qui vous permet de faire

for (MatchResult match : allMatches(pattern, input)) {
  // Use match, and maybe break without doing the work to find all possible matches.
}

en faisant quelque chose comme ça :

public static Iterable<MatchResult> allMatches(
      final Pattern p, final CharSequence input) {
  return new Iterable<MatchResult>() {
    public Iterator<MatchResult> iterator() {
      return new Iterator<MatchResult>() {
        // Use a matcher internally.
        final Matcher matcher = p.matcher(input);
        // Keep a match around that supports any interleaving of hasNext/next calls.
        MatchResult pending;

        public boolean hasNext() {
          // Lazily fill pending, and avoid calling find() multiple times if the
          // clients call hasNext() repeatedly before sampling via next().
          if (pending == null && matcher.find()) {
            pending = matcher.toMatchResult();
          }
          return pending != null;
        }

        public MatchResult next() {
          // Fill pending if necessary (as when clients call next() without
          // checking hasNext()), throw if not possible.
          if (!hasNext()) { throw new NoSuchElementException(); }
          // Consume pending so next call to hasNext() does a find().
          MatchResult next = pending;
          pending = null;
          return next;
        }

        /** Required to satisfy the interface, but unsupported. */
        public void remove() { throw new UnsupportedOperationException(); }
      };
    }
  };
}

Avec ça,

for (MatchResult match : allMatches(Pattern.compile("[abc]"), "abracadabra")) {
  System.out.println(match.group() + " at " + match.start());
}

donne

a at 0
b at 1
a at 3
c at 4
a at 5
a at 7
b at 8
a at 10

94voto

4castle Points 20341

En Java 9, vous pouvez désormais utiliser Matcher#results() pour obtenir un Stream<MatchResult> que vous pouvez utiliser pour obtenir une liste/un tableau de correspondances.

import java.util.regex.Pattern;
import java.util.regex.MatchResult;

String[] matches = Pattern.compile("your regex here")
                          .matcher("string to search from here")
                          .results()
                          .map(MatchResult::group)
                          .toArray(String[]::new);
                    // or .collect(Collectors.toList())

1 votes

Il n'y a pas de méthode results(), veuillez exécuter ceci d'abord.

20 votes

@Bravo Utilisez-vous Java 9 ? Il existe. J'ai mis un lien vers la documentation.

2 votes

:(( existe-t-il une alternative à java 8 ?

25voto

TraderJoeChicago Points 2101

Java rend le regex trop compliqué et ne respecte pas le style perl. Jetez un coup d'œil à MentaRegex pour voir comment vous pouvez accomplir cela en une seule ligne de code Java :

String[] matches = match("aa11bb22", "/(\\d+)/g" ); // => ["11", "22"]

16 votes

Le site MentaRegex est-il en panne ? Lorsque je visite mentaregex.soliveirajr.com il dit seulement "salut"

1 votes

@user64141 on dirait que c'est

0 votes

User64141 il est hors service maintenant mais il est disponible sur l'archive internet web.archive.org/web/20130317004214/http://…

15voto

Bozho Points 273663

Voici un exemple simple :

Pattern pattern = Pattern.compile(regexPattern);
List<String> list = new ArrayList<String>();
Matcher m = pattern.matcher(input);
while (m.find()) {
    list.add(m.group());
}

(si vous avez plusieurs groupes de capture, vous pouvez vous référer à eux par leur index comme argument de la méthode group. Si vous avez besoin d'un tableau, utilisez list.toArray() )

0 votes

Pattern.matches(input) ne fonctionne pas. Vous devez passer votre motif regex (encore !) --> WTF Java ?! pattern.matches(String regex, String input) ; Voulez-vous dire pattern.matcher(input) ?

0 votes

@ElMac Pattern.matches() est une méthode statique, vous ne devez pas l'appeler sur un fichier Pattern instance. Pattern.matches(regex, input) est simplement un raccourci pour Pattern.compile(regex).matcher(input).matches() .

5voto

Anthony Accioly Points 10501

De la Pistes officielles de Regex en Java :

        Pattern pattern = 
        Pattern.compile(console.readLine("%nEnter your regex: "));

        Matcher matcher = 
        pattern.matcher(console.readLine("Enter input string to search: "));

        boolean found = false;
        while (matcher.find()) {
            console.format("I found the text \"%s\" starting at " +
               "index %d and ending at index %d.%n",
                matcher.group(), matcher.start(), matcher.end());
            found = true;
        }

Utilisez find et insérer le résultat group à votre tableau / liste / quoi que ce soit.

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