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

Regex to extract key-value pairs separated by space, with space in values

假设一个包含多个连续键值对的单行字符串,由 space 分隔,但 space 也允许在值内(而不是在键中),例如

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" 可以是任何字符序列,不包括 space.

尝试一些简单的东西,比如

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

或类似的变化是不够的。

是否有正则表达式可以完全处理此类提取,而无需任何进一步的字符串处理?

而不是正则表达式,我建议您使用 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"

</code> 包含键和 <code> 值:

(key\d+)=(.*?)(?= key\d+|$)

用 Java 中的 \ 转义 \:

(key\d+)=(.*?)(?= key\d+|$)

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

尝试 lookahead:

(\b\w+)=(.*?(?=\s\w+=|$))

作为 Java 字符串:

"(\b\w+)=(.*?(?=\s\w+=|$))"

Test at regex101.com; Test at regexplanet(点击"Java")

如果不重复空格,也可能出现类似的情况:

([^\s=]+)=([^=]+(?=\s|$))

否则你可以这样写:

([^\s=]+)=([^=]+\b(?=\s|$))

如果键名不太长,这些模式是一个很好的解决方案,因为它们使用了回溯。

你也可以这样写,最多回溯一步:

([^\s=]+)=(\S+(?>\s+[^=\s]+)*(?!=))