Java正则表达式提取带或不带引号的字段

时间:2014-08-05 08:31:36

标签: java regex string quotes key-value

我试图从两个基本形式的长字符串中提取键值对,一个带有一个带引号,一个没有引号,如

... 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个键的版本),还是应该使用字符串处理?

更棘手的问题:如果有这样的正则表达式,是否还有任何方法可以保持匹配器组的索引对应于值常量,以便引用的字段值和不带引号的字段值对应于同一组指数?

4 个答案:

答案 0 :(得分:8)

您可以将正则表达式修改为以下内容:

/\b(\w+)\s*=\s*(?:"([^"]*)"|([^ ]*)\b)/

值得注意的变化:

  • 您可以在java中使用\w+来捕获单词字符[A-Za-z0-9_]
  • 您无需将=包裹在非捕获组(?:=)中。
  • 交替现在包含在非捕获组中。
  • 匹配应仅在"未完成时以字边界结尾。

请参阅以下代码:

{
    String input = "a =\"First Field\" b=SecondField c3= \"Third field value\" delta = \"\" e_value  = five!";
    String regex = "\\b(\\w+)\\s*=\\s*(?:\"([^\"]*)\"|([^ ]*)\\b)";
    Matcher matcher = Pattern.compile(regex).matcher(input);
    while (matcher.find())
        System.out.println(matcher.group(1) + " = " +
        (matcher.group(2) == null ? matcher.group(3) : matcher.group(2)));
}

查看regex democode demo

  

代码演示STDOUT

a = First Field
b = SecondField
c3 = Third field value
delta = 
e_value = five

答案 1 :(得分:3)

从索引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

答案 2 :(得分:3)

你的java正则表达式" \ b(a | b)\ s *(?:=)\ s *(" [^"] " | [^ ] )\ b"将产生输出:

a = "First
b = SecondField

由于'"''不是\ b边界。因此,您的第一个名称/值对与quotaiton永远不会匹配 你可以改变它:

"\b(a|b)\s*=\s*(?:"([^"]*)"|([^ ]*))"

整个示例代码如下所示:

String input = "a=\"First Field\" b=SecondField";
String regex = "\\b(a|b)\\s*=\\s*(?:\"([^\"]*)\"|([^ ]*))";
Matcher matcher = Pattern.compile(regex).matcher(input);
while (matcher.find()) {
    if(matcher.group(2) != null) {
        System.out.println(matcher.group(1) + " = " + matcher.group(2));
    }else {
        System.out.println(matcher.group(1) + " = " + matcher.group(3));
    }
}

输出如下:

a = First Field
b = SecondField

与此同时,如果您的密钥不仅仅是“a”或“b”,那么您可以将(a | b)变为(\ w +)

答案 3 :(得分:0)

    (a|b)\s*(?:=)\s*("[^"]*"|[^ ]*)

试过这个。工作正常。 http://regex101.com/r/zR7cW9/1