Создать массив совпадений регулярных выражений

В Java я пытаюсь вернуть все совпадения регулярных выражений в массив, но кажется, что вы можете только проверить, соответствует ли шаблон чему-либо или нет (логическое значение).

Как я могу использовать соответствие регулярному выражению, чтобы сформировать массив всех строк, соответствующих выражению регулярного выражения в данной строке?

Ответ 1

(4castle ответ лучше, чем приведенный ниже, если вы можете предположить, Java> = 9)

Вам нужно создать сопоставление и использовать его для итеративного поиска совпадений.

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

После этого allMatches содержит совпадения, и вы можете использовать allMatches.toArray(new String[0]) чтобы получить массив, если он вам действительно нужен.


Вы также можете использовать MatchResult для написания вспомогательных функций для зацикливания совпадений, поскольку Matcher.toMatchResult() возвращает снимок текущего состояния группы.

Например, вы можете написать ленивый итератор, чтобы

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

делая что-то вроде этого:

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

С этим,

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

доходность

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

Ответ 2

В Java 9 теперь вы можете использовать Matcher#results() чтобы получить Stream<MatchResult> который вы можете использовать для получения списка/массива совпадений.

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

Ответ 3

Java делает регулярное выражение слишком сложным и не соответствует perl-стилю. Взгляните на MentaRegex, чтобы узнать, как это можно сделать в одной строке кода Java:

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

Ответ 4

Вот простой пример:

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

(если у вас больше групп захвата, вы можете ссылаться на них по их индексу в качестве аргумента группового метода. Если вам нужен массив, используйте list.toArray())

Ответ 5

С официальных Regex 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;
        }

Используйте find и вставьте полученную group в ваш массив /List/что угодно.

Ответ 6

        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;