我正在尝试以两种基本形式从长字符串中提取键值对,一种是带引号的,另一种是不带引号的,例如

... 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




如果只寻找ab键,则只需对正则表达式模式进行一些更改。

\w+替换第一个a|b

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


这是DEMO



编辑

根据帖子的编辑

只需添加\s来检查空格。

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


DEMO

08-05 06:23