Home > Software design >  Can not extract the values when a user enter an escape character
Can not extract the values when a user enter an escape character

Time:10-31

Given a string input like this: Key=Value;key1=value1;key2=value2;key3=value3; and using the ; as a separator, and also we can use \; in the value to be ; in the runtime.

The problem comes when a user put an input like this Key=Value\;key1=value1\;key2=value2\;key3=value3; when I extract the value it gives us a map like this 1 key (Key) and the value (Value;key1=value1;key2=value2;key3=value3;)

Expecting a map of keys and values. 4 keys (Key,Key1,Key2,Key3) and 4 values (Value,Value1,Value2,Value3)

Constraints:

  1. The value can be any string.
  2. The value can contain another key. Ex. key=value;key1=value=123; so we have 2 keys and value of the second may includes the first key.
  3. The key can be any string.
  4. can be any number of keys and value.
  5. The value can be empty.
  6. we have a list of the keys, but the user might not add all of them.

Tried more than regex, but still not completely getting it right. This is the regex currently using:

([\\n\\s]*(. ?)=(.*?;?);[\\n\\s]*)

But can you help with the regex or introduce a new algorithm

CodePudding user response:

As far as i understand it, the user is responsible for escaping caracters like ;. If that is true, wouldn't it be reasonable to require them to escape \ as well?

So using \ alone at the end, would cause the input string to be invalid in the same way as using ; without escaping it. Hence, if the user wants to input \ it should been escaped the same way as before \\.

CodePudding user response:

[EDITED] If you allow escaped delimiters (\= to be in the key and \; to be in the value) then you could use lookbehinds to match the real delimiters:

\b(. ?)(?<!\\)=(. ?)(?<!\\);

Regex101

CodePudding user response:

There are a few things that puzzle me in your question, and I regret that you didn't provide any code. For instance, why would you need a backslash before semicolons?

That said, you could try something like this:

private static final Pattern RE
        = Pattern.compile("\\s*([^=;] )=((?:[^;\\\\]|\\\\;|\\\\\\\\)*)\\s*;\\s*");

private static Map<String,String> toMap(String input) {
    Map<String,String> map = new HashMap<>();
    Matcher matcher = RE.matcher(input);
    while (matcher.find()) {
        map.put(matcher.group(1), matcher.group(2));
    }
    return map;
}

It works with:

    String input = "URL=https://postman-echo.com/post;Method=POST;Headers=Content-Type:application/json\\; charset=utf-8\\;;Body=fileName;Cookies Variable Name=;File Path=C:\\s.png;Response Variable Name=ResponseResult;Status Code Variable Name=StatusCode;Response Cookies Variable Name=ResponseCookies;";
    Map<String,String> map = toMap(input);

Result:

Cookies Variable Name = 
Headers = Content-Type:application/json\; charset=utf-8\;
Response Cookies Variable Name = ResponseCookies
Response Variable Name = ResponseResult
Method = POST
Status Code Variable Name = StatusCode
Body = fileName
URL = https://postman-echo.com/post
  • Related