假设一个单行字符串有多个连续的键值对,用空格分隔,但允许的值也在值内(不在键中),例如。
key1=one two three key2=four key3=five six key4=seven eight nine ten
从上面正确提取键值对将产生以下映射:
"key1", "one two"
"key2", "four"
"key3", "five six"
"key4", "seven eight nine ten"
其中“keyX”可以是任何字符序列,不包括空格。
尝试简单的事情,比如
([^=]+=[^=]+)+
或类似的变化是不够的。
是否有正则表达式来完全处理这种提取,而不进行任何进一步的字符串处理?
答案 0 :(得分:11)
尝试使用lookahead:
(\b\w+)=(.*?(?=\s\w+=|$))
作为Java字符串:
"(\\b\\w+)=(.*?(?=\\s\\w+=|$))"
Test at regex101.com; Test at regexplanet(点击“Java”)
答案 1 :(得分:3)
\1
包含密钥和\2
值:
(key\d+)=(.*?)(?= key\d+|$)
在Java中使用\
转义\\
:
(key\\d+)=(.*?)(?= key\\d+|$)
答案 2 :(得分:1)
而不是正则表达式,我建议你使用indexOf
解析它。像,
String in = "key1=one two three key2=four key3=five six "
+ "key4=seven eight nine ten";
Map<String, String> kvp = new LinkedHashMap<>();
int prev = 0;
int start;
while ((start = in.indexOf("key", prev)) != -1) {
// Find the next "=" sign.
int eqlIndex = in.indexOf("=", start + 3);
// Find the end... maybe the end of the String.
int end = in.indexOf("key", eqlIndex + 1);
if (end == -1) {
// It's the end of the String.
end = in.length();
} else {
// One less than the next "key"
end--;
}
kvp.put(in.substring(start, eqlIndex),
in.substring(eqlIndex + 1, end).trim());
prev = start + 3;
}
for (String key : kvp.keySet()) {
System.out.printf("%s=\"%s\"%n", key, kvp.get(key));
}
输出
key1="one two three"
key2="four"
key3="five six"
key4="seven eight nine ten"
答案 3 :(得分:1)
如果没有重复空格,也可以这样:
([^\\s=]+)=([^=]+(?=\\s|$))
否则你总能写下这个:
([^\\s=]+)=([^=]+\\b(?=\\s|$))
如果关键名称不长,因为它们使用回溯,这些模式是一个很好的解决方案。
你也可以写这个最需要回溯的一步:
([^\\s=]+)=(\\S+(?>\\s+[^=\\s]+)*(?!=))