我试图从两个基本形式的长字符串中提取键值对,一个带有一个带引号,一个没有引号,如
... 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个键的版本),还是应该使用字符串处理?
更棘手的问题:如果有这样的正则表达式,是否还有任何方法可以保持匹配器组的索引对应于值常量,以便引用的字段值和不带引号的字段值对应于同一组指数?
答案 0 :(得分:8)
您可以将正则表达式修改为以下内容:
/\b(\w+)\s*=\s*(?:"([^"]*)"|([^ ]*)\b)/
值得注意的变化:
\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)));
}
代码演示
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
如果您只想查找a
和b
个密钥,那么只需对正则表达式进行细微更改。
将第一个\w+
替换为a|b
(a|b)=(?:")?(.*?(?="?\s+\w+=|(?:"?)$))
这是DEMO
根据帖子的编辑
只需添加\s
即可检查空格。
(\w+)\s*=\s*(?:")?(.*?(?="?\s+\w+\s*=|(?:"?)$))
答案 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