0

I have tried alterations using '|' but seems to be impossible to first parse map if possible, if not, just parse the value as a whole, but keeping the capture group as no 1/2, tried with branch reset group but didn't manage that way either. Any suggestions are welcome.

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

class Scratch {

  public static void main(String[] args) {

    final Pattern outerKeyPattern = Pattern.compile("([A-Z]+)\\((.*)\\)", Pattern.MULTILINE);
    final Pattern innerPattern = Pattern.compile("([A-Z]+)\\((.*?)\\)");

    // There will always be a value in the outer, 
    // but sometimes it's an inner map, i.e only need to solve this case, no other exeptions
 
    String input = """
      VALUE(123)
      OUTERVALUE(INNERVALUE(123)OTHERVALUE(456))
      """;

    Map<String, Map<String, String>> outer = new HashMap<>();
    Matcher matcher = outerKeyPattern.matcher(input);
    while (matcher.find()) {
      String key = matcher.group(1);
      String value = matcher.group(2);
      Matcher valueMatcher = innerPattern.matcher(value);
      Map<String, String> innerMap = new HashMap<>();
      while (valueMatcher.find()) {
        innerMap.put(valueMatcher.group(1), valueMatcher.group(2));
      }
      outer.put(key, innerMap);
    }

    System.out.println(outer);
  }
}

yields output:

{VALUE={}, OUTERVALUE={INNERVALUE=123, OTHERVALUE=456}}

I need to parse value also as key for the inner map and it's value as null:

{VALUE={123=}, OUTERVALUE={INNERVALUE=123, OTHERVALUE=456}}
Viktor Mellgren
  • 4,318
  • 3
  • 42
  • 75
  • 1
    Avoid using `.*` if you can't control it's range of effect. – lemon Jan 18 '23 at 11:43
  • 1
    Your question is quite unclear to me, as it starts with 'I have tried alternatives'. Can you explain what goes wrong and what you expect? – Marja van der Wind Jan 18 '23 at 12:03
  • @MarjavanderWind https://www.regular-expressions.info/alternation.html I expect to be able to parse a string like X(1) as (X,{1,"") and as string like X(Y(1)Z(1) as (X,{{Y,1},{Z,1}) the issue I''m having is that i need to be able to have alternate capture groups depending on if it's a single value, or if it is a "map". – Viktor Mellgren Jan 18 '23 at 12:41

1 Answers1

1

Since you seem to process your data line by line and the comment in your snippet indicates that your data is well formed, you could first extract the whole content of the outter braces and then check if the value contains any nested key-value pairs. With some modifications to your regex, something like below might be what you are looking for:

public static void main(final String[] args) {

    Pattern outerPattern = Pattern.compile("([A-Z]+)\\((.*)\\)");
    Pattern innerPattern = Pattern.compile("([A-Z]+)\\(([^()]*)\\)");

    String input = """
            VALUE(123)
            OUTERVALUE(INNERVALUE(123)OTHERVALUE(456))
            """;

    Map<String, Map<String, String>> outer = new HashMap<>();

    input.lines().forEach(line -> {
        Matcher matcher = outerPattern.matcher(line);
        matcher.find();

        String key   = matcher.group(1);
        String value = matcher.group(2);

        Map<String, String> innerMap = new HashMap<>();

        if (!innerPattern.asPredicate().test(value)) {       //check if value doesn't contain any nested key-value-pairs
            innerMap.put(value, "");
        } else {
            Matcher valueMatcher = innerPattern.matcher(value);
            while (valueMatcher.find()) {
                innerMap.put(valueMatcher.group(1), valueMatcher.group(2));
            }
        }
        outer.put(key, innerMap);
    });

    System.out.println(outer);
}
Eritrean
  • 15,851
  • 3
  • 22
  • 28
  • Realized my phrasing and needs was unclear while trying to minimize the example for recreation and removing company secrets, this is a reused piece of code that takes different regexes depending on type of file, so cannot change the structure too much. I.e. was only looking for fixes on the regex itself. – Viktor Mellgren Jan 26 '23 at 08:26