我正在尝试以两种基本形式从长字符串中提取键值对,一种是带引号的,另一种是不带引号的,例如
... a="First Field" b=SecondField ...
使用
Java
正则表达式\b(a|b)\s*(?:=)\s*("[^"]*"|[^ ]*)\b
但是,运行以下测试代码
public static void main(String[] args) {
String input = "a=\"First Field\" b=SecondField";
String regex = "\\b(a|b)\\s*(?:=)\\s*(\"[^\"]*\"|[^ ]*)\\b";
Matcher matcher = Pattern.compile(regex).matcher(input);
while (matcher.find()) {
System.out.println(matcher.group(1) + " = " + matcher.group(2));
}
}
输出是
a = "First
b = SecondField
而不是所需的(不带引号)
a = First Field
b = SecondField
在更笼统的输入中,例如
a ="First Field" b=SecondField c3= "Third field value" delta = "" e_value = five!
输出应为(同样,不带引号,并且在
=
符号前后带有不同数量的空白)a = First Field
b = SecondField
c3 = Third field value
delta =
e_value = five!
是否有一个涉及上述用例的正则表达式(至少具有2个键的版本),还是应该采用字符串处理?
甚至更棘手的问题是:如果存在这样的正则表达式,是否还有任何方法可以使匹配器组的索引对应于该值恒定,以使带引号的字段值和不带引号的字段值都对应于同一组索引?
最佳答案
从索引1和2获取匹配的组
(\w+)=(?:")?(.*?(?="?\s+\w+=|(?:"?)$))
这是DEMO
样例代码:
String str = "a=\"First Field\" b=SecondField c=\"ThirdField\" d=\"FourthField\"";
Pattern p = Pattern.compile("(\\w+)=(?:\")?(.*?(?=\"?\\s+\\w+=|(?:\"?)$))");
Matcher m = p.matcher(str);
while (m.find()) {
System.out.println("key : " + m.group(1) + "\tValue : " + m.group(2));
}
输出:
key : a Value : First Field
key : b Value : SecondField
key : c Value : ThirdField
key : d Value : FourthField
如果只寻找
a
和b
键,则只需对正则表达式模式进行一些更改。用
\w+
替换第一个a|b
(a|b)=(?:")?(.*?(?="?\s+\w+=|(?:"?)$))
这是DEMO
编辑
根据帖子的编辑
只需添加
\s
来检查空格。(\w+)\s*=\s*(?:")?(.*?(?="?\s+\w+\s*=|(?:"?)$))
DEMO