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

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

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

尝试一些简单的事情,比如

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

或类似的变化是不够的。

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

尝试前瞻 :

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

作为Java字符串:

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

在regex101.com进行测试 ; 在regexplanet上测试 (点击“Java”)

\1包含键和\2值:

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

在Java中使用\\转义\

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

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

而不是正则表达式,我建议你使用indexOf解析它。 就像是,

 String in = "key1=one two three key2=four key3=five six " + "key4=seven eight nine ten"; Map 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" 

如果没有重复空格,也可以这样:

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

否则你总能写下这个:

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

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

你也可以写这个最多需要一步回溯的东西:

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