Splitting a sentence in words where word(s) also include multiple spaces by using regular expression

Viewed 84

Having a sentence with multiple spaces by using regular expression I try to achieve the following:

example of sentence: This     is a simple text.

Expected result:[This,     is, a, simple, text.]

Actual result: [This, is, a, simple, text.]

ArrayList<String> tokens = new ArrayList<>();
Pattern tokSplitter = Pattern.compile("[a-zA-Z.*//s*]+");
Matcher m = tokSplitter.matcher("This     is a simple text.");
    while (m.find()) {
            tokens.add(m.group());
    }
    System.out.println(tokens);
4 Answers

I think using lookaround is the simplest way to solve your issue.

Pattern tokSplitter = Pattern.compile("(?<=\\S)\\s");
String str = "This     is a simple text.";
ArrayList<String> tokens = Arrays.asList(tokSplitter.split(str));
System.out.println(tokens);

You can write something like:

public static void main(String[] args) {
    ArrayList<String> tokens = new ArrayList<>();
    Pattern tokSplitter = Pattern.compile("(\\s*[a-zA-Z.]+)\\s?");
    Matcher m = tokSplitter.matcher("This     is a simple text.");
    while (m.find()) {
        tokens.add(m.group(1));
    }
    System.out.println(tokens);
}

out: [This, is, a, simple, text.]

You are using the wrong tool for the job. If you want to split a string, use the split operation:

List<String> tokens = Arrays.asList("This     is a simple text.".split("\\b "));

This produces a list with the same contents as the currently accepted answer. It’s worth noting that both solutions consume one delimiting space and only keep additional spaces whereas the output of System.out.println(tokens); is [This, is, a, simple, text.] because the toString() method of all standard List implementations inserts a space after each comma.

If you want to retain all spaces, you would have to use

List<String> tokens = Arrays.asList("This     is a simple text.".split("\\b(?= )"));

instead. The actual result strings can be seen when using:

tokens.forEach(s -> System.out.println('"'+s+'"'));
"This"
"     is"
" a"
" simple"
" text."

compared to

"This"
"    is"
"a"
"simple"
"text."

of the other solutions.

If you want to deal with Pattern directly, e.g. to be able to reuse it, it still doesn’t stop you from using split instead of a match loop:

Pattern wordEnd = Pattern.compile("\\b(?= )");
List<String> tokens = Arrays.asList(wordEnd.split("This     is a simple text."));
tokens.forEach(s -> System.out.println('"'+s+'"'));

Here is a simple pattern to solve your task: \s*\S+

Demo.

The code will be:

ArrayList<String> tokens = new ArrayList<>();
Pattern tokSplitter = Pattern.compile("\\s*\\S+");
Matcher m = tokSplitter.matcher("This     is a simple text.");
    while (m.find()) {
            tokens.add(m.group());
    }
    System.out.println(tokens);
Related