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:
- The value can be any string.
- 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.
- The key can be any string.
- can be any number of keys and value.
- The value can be empty.
- 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(. ?)(?<!\\)=(. ?)(?<!\\);
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