Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create array of regex matches

Tags:

java

regex

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?

like image 800
Jake Sankey Avatar asked May 16 '11 16:05

Jake Sankey


People also ask

How do you match periods in regex?

The period (.) represents the wildcard character. Any character (except for the newline character) will be matched by a period in a regular expression; when you literally want a period in a regular expression you need to precede it with a backslash.

How do you find how many occurrences of a regex pattern were replaced in a string?

To count a regex pattern multiple times in a given string, use the method len(re. findall(pattern, string)) that returns the number of matching substrings or len([*re. finditer(pattern, text)]) that unpacks all matching substrings into a list and returns the length of it as well.

What is regex matching pattern?

A regex pattern matches a target string. The pattern is composed of a sequence of atoms. An atom is a single point within the regex pattern which it tries to match to the target string. The simplest atom is a literal, but grouping parts of the pattern to match an atom will require using ( ) as metacharacters.


2 Answers

(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 
like image 156
Mike Samuel Avatar answered Oct 02 '22 22:10

Mike Samuel


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()) 
like image 30
4castle Avatar answered Oct 02 '22 22:10

4castle