Extract keys values from string with space in values

Viewed 85

I'm learning about regex and attempting to extract from this string:

"a,b,c,test1=0 test2=1 test3=2 test4=3 Request t=4,test6_r_a=5,d,e,f"

the key/values:

test1=0 
test2=1 
test3=2 
test4=3 
Request t=4
test6_r_a=5

I use this regex :

"\\p{Alnum}+ *=(?: *\\p{Alnum}+)+ "

which produces :

test1=0 
test2=1 
test3=2 
test4=3 test5 Request 

The key,value pairs : Request t=4,test6_r_a=5 are not matched.

What modification of regex is required to match the expected values ?

src :

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ExtractMatch {

    public static void main(String args[]) {
        final String text = "a,b,c,test1=0 test2=1 test3=2 test4=3 test5 Request t=4,test6_r_a=5,d,e,f";
        final Pattern pattern = Pattern.compile("\\p{Alnum}+ *=(?: *\\p{Alnum}+)+ ");
        final Matcher matcher = pattern.matcher(text);
        while (matcher.find()) {
            System.out.println(matcher.group());
        }
    }
}

I'm attempting to allow the scenario where variable number of spaces can be within key, for example "Request t" or "Request t d"

update :

The string to be parsed is :

"a,b,c,test1=0 test2=1 test3=2 test4=3 t Request=4,test6_r_a=5,d,e,f"

I've updated regex posted in answer by anubhava to use

"\\w+=\\w+(?:\\h+\\d+)*\\b(?!=)"

instead of :

"\\w+=\\w+(?:\\h+\\w+)*\\b(?!=)"

which produces :

test1=0
test2=1
test3=2
test4=3
Request=4
test6_r_a=5

But I'm expecting :

test1=0
test2=1
test3=2
test4=3
t Request=4
test6_r_a=5

src :

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ExtractMatch {

    public static void main(String args[]) {
        final String text = "a,b,c,test1=0 test2=1 test3=2 test4=3 t Request=4,test6_r_a=5,d,e,f";
        final Pattern pattern = Pattern.compile("\\w+=\\w+(?:\\h+\\d+)*\\b(?!=)");
        final Matcher matcher = pattern.matcher(text);
        while (matcher.find()) {
            System.out.println(matcher.group());
        }
    }
}
3 Answers

You may use this regex for matching all kep=value pairs:

\w+(?:\h+\w+)*=\w+

RegEx Demo

RegEx Details:

  • \w+: Match 1+ word characters as key start word
  • (?:\h+\w+)*: Match space separated 0 or more words
  • =: Match a =
  • \w+: Match 1+ word characters

Code:

final String text = "a,b,c,test1=0 test2=1 test3=2 test4=3 t Request=4,test6_r_a=5,d,e,f";
final Pattern pattern = Pattern.compile("\\w+(?:\\h+\\w+)*=\\w+");
final Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
    System.out.println(matcher.group());
}

Using \p{Alnum} does not match an underscore.

You might use matching word characters like:

\w+(?:\h+\w+)*=\w+

Explanation

  • \w+ Match 1+ word chars
  • (?:\h+\w+)* Optionally repeat matching 1+ horizontal whitespace chars and 1+ word chars
  • = Match literally
  • \w+ Match 1+ word chars

Regex demo | Java demo

final String text = "a,b,c,test1=0 test2=1 test3=2 test4=3 t Request=4,test6_r_a=5,d,e,f";
final Pattern pattern = Pattern.compile("\\w+(?:\\h+\\w+)*=\\w+");
final Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
    System.out.println(matcher.group());
}

Output

test1=0
test2=1
test3=2
test4=3
t Request=4
test6_r_a=5

Or a version with \p{Alnum} and an undercore in a character class:

[\p{Alnum}_]+(?:\h+[\p{Alnum}_]+)*=[\p{Alnum}_]+

Regex demo

Used regex:

"(?<=,|\\W)([^,]+?=\\w+)"

It is also supporting match like "Request t d".

Read about regex constructs here: https://docs.oracle.com/javase/10/docs/api/java/util/regex/Pattern.html

Testbench and regex in context:

public static void main(String[] args) throws IOException {
    String input = "a,b,c,test1=0 test2=1 test3=2 test4=3 Request t=4 Request t d=42,test6_r_a=5,d,e,f";

    Matcher matcher = Pattern.compile("(?<=,|\\W)([^,]+?=\\w+)").matcher(input);

    while(matcher.find()) {
        System.out.printf("'%s'%n", matcher.group(1));
    }
}

Output:

'test1=0'
'test2=1'
'test3=2'
'test4=3'
'Request t=4'
'Request t d=42'
'test6_r_a=5'
Related