Joe
Joe

Reputation: 191

Regex: capture group in list like string

I've searched stacked overflow and the net and I found similar questions but none that gave me a concrete answer. I have a string that acts as a list with the following formatting Key(Value)/Key(value)/Key(value,value)). I would like to match them by key name IF the key exists, so I don't really want the parenthesis included anywhere.. just the key and the value. I coded something out, but it's a real mess...

so my conditions are: 1)extract key value pairs without parenthesis 2)extract IF they are available... 3)If value portion of list contains two values delimited by a ",", extract individually

textToParse =     "TdkRoot(0x0)/Tdk(0x2,0x0)/Tdk(0x0,0x1)/VAL(40A8F0B32240,2x4)/SN(0000:0000:0000:0000:0000:0000:0000:0000/IP(000.1.000.1)/Blue(2x4,2x4)"

String patternText = "^TdkRoot\(( [A-Za-z0-9]) Tdk\(( \\w}+) VAL\(( \\w) SN\(( \\w) IP\     (( \\w) Blue\(( \\w)"  

Pattern pattern = Pattern.compile( patternText );  
Matcher matcher = pattern.matcher(textToParse);  

//Extract the groups from the regex (e.g. elements in braces)  
String messageId = matcher.group( 1 );  
String submitDate = matcher.group(4);  
String statusText = matcher.group( 6 );  

I think a cleaner/easier approach would be to extract the elements using patterns for each individual key/value. If so what pattern could I use to tell regex: for "key" grab "value" but leave the parenthesis... if value is delimited by a coma.. return array?? possibly?

Thanks Community!! Hope to hear from you!

PS I know (?<=\()(.*?)(?=\)) will capture anything in the parentheses "(This) value was captured), but how can I modify that to specify a key before the parentheses? "I want to capture whats in THIS(parentheses)" ... key THIS possibly delimited by a coma

Upvotes: 0

Views: 1388

Answers (2)

TheLostMind
TheLostMind

Reputation: 36304

public static void main(String[] args) {
    String textToParse = "TdkRoot(0x0)/Tdk(0x2,0x0)/Tdk(0x0,0x1)/VAL(40A8F0B32240,2x4)/SN(0000:0000:0000:0000:0000:0000:0000:0000)/IP(000.1.000.1)/Blue(2x4,2x4)";
    Pattern p = Pattern.compile("(\\w+)\\((.*?)\\)");
    Matcher m = p.matcher(textToParse);
    while (m.find()) {
        System.out.println("key :" + m.group(1));
        if (m.group(2).contains(",")) {
            String[] s = m.group(2).split(",");
            System.out.println("values : " + Arrays.toString(s));
        } else {
            System.out.println("value :" + m.group(2));
        }

    }
}

o/p:

key :TdkRoot
value :0x0
key :Tdk
values : [0x2, 0x0]
key :Tdk
values : [0x0, 0x1]
key :VAL
values : [40A8F0B32240, 2x4]
key :SN
value :0000:0000:0000:0000:0000:0000:0000:0000
key :IP
value :000.1.000.1
key :Blue
values : [2x4, 2x4]

Upvotes: 3

SamYonnou
SamYonnou

Reputation: 2068

Not sure if this is what you are looking for (your sample code does not compile) but the following code parses the input text into a map :

String inputText = "TdkRoot(0x0)/Tdk(0x2,0x0)/Tdk(0x0,0x1)/VAL(40A8F0B32240,2x4)/SN(0000:0000:0000:0000:0000:0000:0000:0000)/IP(000.1.000.1)/Blue(2x4,2x4)";

Pattern outerPattern = Pattern.compile("([^/()]+)\\(([^()]+)\\)");
Pattern innerPattern = Pattern.compile("([^,]+)");

Map<String, Collection<String>> parsedData = new HashMap<String, Collection<String>>();

Matcher outerMatcher = outerPattern.matcher(inputText);
while (outerMatcher.find()) {
  String key = outerMatcher.group(1);
  String val = outerMatcher.group(2);

  Collection<String> valueCollection = new ArrayList<String>();

  Matcher innerMatcher = innerPattern.matcher(val);
  while (innerMatcher.find()) {
    valueCollection.add(innerMatcher.group(1));
  }

  parsedData.put(key, valueCollection);
}

System.out.println(parsedData);

The resulting map (printed on last line) is

{Blue=[2x4, 2x4], VAL=[40A8F0B32240, 2x4], IP=[000.1.000.1], TdkRoot=[0x0], SN=[0000:0000:0000:0000:0000:0000:0000:0000], Tdk=[0x0, 0x1]}

Upvotes: 1

Related Questions