正则表达式提取由空格分隔的键值对,值为空格

时间:2015-01-24 22:31:14

标签: java regex key-value keyvaluepair

假设一个单行字符串有多个连续的键值对,用空格分隔,但允许的值也在值内(不在键中),例如。

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”可以是任何字符序列,不包括空格。

尝试简单的事情,比如

([^=]+=[^=]+)+

或类似的变化是不够的。

是否有正则表达式来完全处理这种提取,而不进行任何进一步的字符串处理?

4 个答案:

答案 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+|$)

演示:https://regex101.com/r/dO8kM2/1

答案 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]+)*(?!=))