web-dev-qa-db-fra.com

Créer un tableau de correspondances de regex

En Java, j'essaie de renvoyer toutes les correspondances de regex à un tableau, mais il semble que vous ne pouvez vérifier que si le motif correspond à quelque chose ou non (boolean).

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

138
Jake Sankey

( La réponse de 4castle est meilleur que celui ci-dessous si vous pouvez supposer que Java> = 9)

Vous devez créer un matcher et l'utiliser pour rechercher 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 cela, allMatches contient les correspondances et vous pouvez utiliser allMatches.toArray(new String[0]) pour obtenir un tableau si vous en avez réellement besoin.


Vous pouvez également utiliser MatchResult pour écrire des fonctions d'assistance permettant de boucler des correspondances, car Matcher.toMatchResult() renvoie un instantané de l'état du groupe actuel.

Par exemple, vous pouvez écrire un itérateur paresseux pour vous permettre 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());
}

les rendements

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

Dans Java 9, vous pouvez maintenant 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())
_
33
4castle

Java rend les expressions rationnelles trop compliquées et ne suit pas le style Perl. Jetez un oeil à MentaRegex pour voir comment vous pouvez y parvenir en une seule ligne de code Java:

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

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 plus de groupes de capture, vous pouvez les référencer par leur index comme argument de la méthode group. Si vous avez besoin d'un tableau, utilisez list.toArray())

8
Bozho

Depuis le Regex officiel Java Trails :

        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érez le résultat group dans votre tableau/liste/peu importe.

5
Anthony Accioly
        Set<String> keyList = new HashSet();
        Pattern regex = Pattern.compile("#\\{(.*?)\\}");
        Matcher matcher = regex.matcher("Content goes here");
        while(matcher.find()) {
            keyList.add(matcher.group(1)); 
        }
        return keyList;
0
Nikhil Kumar K