Jake Sankey
Jake Sankey

Reputation: 5137

Create array of regex matches

In Java, I am trying to return all regex matches to an array but it seems that you can only check whether the pattern matches something or not (boolean).

How can I use a regex match to form an array of all string matching a regex expression in a given string?

Upvotes: 223

Views: 260917

Answers (7)

ArtBindu
ArtBindu

Reputation: 1972

Finest Solution : reuse of Matcher.find() multiple time:


I'm uploading this answer, as my question is closed as duplicate of this question by the StackOverflow Community.
Java matcher.find() not returning same value for multiple times

Interestingly Java Matcher class have matcher.find(int start) method - Method Overloading

Java Matcher class Method Overloading

Here we need to pass the integer value 0 as start index.
This will reset the matcher and then attempts to find the next.
public class Main {
    public static void main(String[] args) {
        List<String> familyHiearchy = Arrays.asList(
                "A",
                "Level_00/Level_01_first",
                "Level_00/Level_01_second",
                "Level_00/Level_01_first/Level_02_first"
        );
        for (String ele : familyHiearchy) {
            Matcher matcher_child = ((Pattern) Pattern.compile("\\w+$", Pattern.CASE_INSENSITIVE)).matcher(ele);
            Matcher matcher_parent = ((Pattern) Pattern.compile("\\w+(?=/\\w+$)", Pattern.CASE_INSENSITIVE)).matcher(ele);
            System.out.println("-----------------");
            
            if(matcher_child.find(0) && matcher_parent.find(0)) {
                System.out.println("Both Child and Parent are available");
            } else if(matcher_child.find(0) && !matcher_parent.find(0)) {
                System.out.println("Child available, but parent not available");
            }

            if (matcher_child.find(0)) {
                String childName = matcher_child.group();
                System.out.println("Name : " + childName);
            }

            if (matcher_parent.find(0)) {
                String parentName = matcher_parent.group();
                System.out.println("Parent Name : " + parentName);
            }
        }
    }
}

Sample Code: tutorialspoint-solution

Upvotes: 0

TraderJoeChicago
TraderJoeChicago

Reputation: 6315

Java makes regex too complicated and it does not follow the perl-style. Take a look at MentaRegex to see how you can accomplish that in a single line of Java code:

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

Upvotes: 27

Mike Samuel
Mike Samuel

Reputation: 120516

(4castle's answer is better than the below if you can assume Java >= 9)

You need to create a matcher and use that to iteratively find matches.

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

After this, allMatches contains the matches, and you can use allMatches.toArray(new String[0]) to get an array if you really need one.


You can also use MatchResult to write helper functions to loop over matches since Matcher.toMatchResult() returns a snapshot of the current group state.

For example you can write a lazy iterator to let you do

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

by doing something like this:

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

With this,

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

yields

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

Upvotes: 337

castletheperson
castletheperson

Reputation: 33476

In Java 9, you can now use Matcher#results() to get a Stream<MatchResult> which you can use to get a list/array of matches.

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

Upvotes: 133

Bozho
Bozho

Reputation: 597106

Here's a simple example:

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

(if you have more capturing groups, you can refer to them by their index as an argument of the group method. If you need an array, then use list.toArray())

Upvotes: 16

Nikhil Kumar K
Nikhil Kumar K

Reputation: 1117

        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;

Upvotes: 2

Anthony Accioly
Anthony Accioly

Reputation: 22461

From the Official 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;
        }

Use find and insert the resulting group at your array / List / whatever.

Upvotes: 5

Related Questions