我正在使用一种API,该API为我提供了XML,我需要从一个实际上是字符串的标记中获取一张地图。示例:
拥有
Billable=7200,Overtime=false,TransportCosts=20$
我需要
["Billable"="7200","Overtime=false","TransportCosts"="20$"]
问题在于字符串是完全动态的,因此它可能像
Overtime=true,TransportCosts=one, two, three
Overtime=true,TransportCosts=1= 1,two, three,Billable=7200
所以我不能只用逗号然后用等号分开。 是否可以使用正则表达式将类似字符串的内容转换为地图?
到目前为止,我的代码是:
private Map<String, String> getAttributes(String attributes) {
final Map<String, String> attr = new HashMap<>();
if (attributes.contains(",")) {
final String[] pairs = attributes.split(",");
for (String s : pairs) {
if (s.contains("=")) {
final String pair = s;
final String[] keyValue = pair.split("=");
attr.put(keyValue[0], keyValue[1]);
}
}
return attr;
}
return attr;
}
提前谢谢
答案 0 :(得分:2)
您可以使用
(\w+)=(.*?)(?=,\w+=|$)
请参见regex demo。
详细信息
(\w+)
-第1组:一个或多个单词字符=
-等号(.*?)
-第2组:除换行符以外的任何零个或多个字符,并且尽可能少(?=,\w+=|$)
-一个正向的超前查询,需要先输入,
,然后输入1个以上的字符,然后输入=
,或当前位置右边的字符串结尾。Java代码:
public static Map<String, String> getAttributes(String attributes) {
Map<String, String> attr = new HashMap<>();
Matcher m = Pattern.compile("(\\w+)=(.*?)(?=,\\w+=|$)").matcher(attributes);
while (m.find()) {
attr.put(m.group(1), m.group(2));
}
return attr;
}
String s = "Overtime=true,TransportCosts=1= 1,two, three,Billable=7200";
Map<String,String> map = getAttributes(s);
for (Map.Entry entry : map.entrySet()) {
System.out.println(entry.getKey() + "=" + entry.getValue());
}
结果:
Overtime=true
Billable=7200
TransportCosts=1= 1,two, three
答案 1 :(得分:1)
我注意到的第一件事是,很难用您提供的数据来识别定界符,但是似乎可以识别的是,逗号和大写字母将每个字段分开。
这允许使用String.replaceAll("(?<=,)([A-Z])", ",$1")
将定界符更改为使用正则表达式可轻松识别的内容。现在,您将有一个定界符,可以识别(,,)
并拆分数据以在需要的地方插入引号。
类似的东西:
public class StackOverflow {
public static void main(String[] args) {
String [] data = {
"Overtime=true,TransportCosts=one, two, three",
"Overtime=true,TransportCosts=1= 1,two, three,Billable=7200"
};
for (int i = 0; i < data.length; i++) {
data[i] = data[i].replaceAll("(?<=,)([A-Z])", ",$1");
String[] pieces = data[i].split(",,");
for (int j = 0; j < pieces.length; j++) {
int equalIndex = pieces[j].indexOf("=");
StringBuilder sb = new StringBuilder(pieces[j]);
// Insert quotes around the = sign
sb.insert(equalIndex, "\"");
sb.insert(equalIndex + 2, "\"");
// Insert quotes at the beginning and end of the string
sb.insert(0, "\"");
sb.append("\"");
pieces[j] = sb.toString();
}
// Join the pieces back together delimited by a comma
data[i] = String.join(",", pieces);
System.out.println(data[i]);
}
}
}
结果
"Overtime"="true","TransportCosts"="one, two, three"
"Overtime"="true","TransportCosts"="1= 1,two, three","Billable"="7200"
答案 2 :(得分:0)
恕我直言,更简单的正则表达式:([^,]+=[^=]+)(,|$)
([^,]+=[^=]+)
→分组:除逗号外,后跟1个等号,后跟除等号外的所有内容...
(,|$)
→... ...以逗号或行尾分隔
测试:
public static void main(String[] args) {
Pattern pattern = Pattern.compile("([^,]+=[^=]+)(,|$)");
String test1 = "abc=def,jkl,nm=ghi,egrh=jh=22,kdfka,92,kjasd=908@0982";
System.out.println("Test 1: "+test1);
Matcher matcher = pattern.matcher(test1);
while (matcher.find()) {
System.out.println(matcher.group(1));
}
System.out.println();
String test2 = "Overtime=true,TransportCosts=1= 1,two, three,Billable=7200";
System.out.println("Test 2: "+test2);
matcher = pattern.matcher(test2);
while (matcher.find()) {
System.out.println(matcher.group(1));
}
}
输出:
Test 1: abc=def,jkl,nm=ghi,egrh=jh=22,kdfka,92,kjasd=908@0982
abc=def,jkl
nm=ghi
egrh=jh=22,kdfka,92
kjasd=908@0982
Test 2: Overtime=true,TransportCosts=1= 1,two, three,Billable=7200
Overtime=true
TransportCosts=1= 1,two, three
Billable=7200
答案 3 :(得分:0)
我使用番石榴看到了这段代码
import com.google.common.base.Splitter;
/**
* parse string 'prop1=val1; prop2=val2' to map
*/
public static Map<String, String> parseMap(final String keyValueString) {
if (StringUtils.isEmpty(keyValueString)) return Collections.emptyMap();
return Splitter.on(";")
.trimResults()
.withKeyValueSeparator('=')
.split(keyValueString);
}
一个便笺,Idea显示警告,因为Splitter
带有注释
com.google.common.annotations.Beta
不错,但是在guava库版本更新期间可能需要一些工作。