正则表达式提取由 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+|$)
尝试 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]+)*(?!=))
假设一个包含多个连续键值对的单行字符串,由 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+|$)
尝试 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]+)*(?!=))