Java正则表达式在多个分隔符上拆分,包括其他分隔符的子字符串
我正在尝试使用正则表达式和已知分隔符将字符串转换为值映射。我拥有的代码可以工作,但是如果我使用的分隔符是另一个分隔符的子字符串,它就不会被解析(正确地) 让我们直接切入一些示例输入、错误输出、预期输出和代码 示例输入:Java正则表达式在多个分隔符上拆分,包括其他分隔符的子字符串,java,regex,dictionary,split,Java,Regex,Dictionary,Split,我正在尝试使用正则表达式和已知分隔符将字符串转换为值映射。我拥有的代码可以工作,但是如果我使用的分隔符是另一个分隔符的子字符串,它就不会被解析(正确地) 让我们直接切入一些示例输入、错误输出、预期输出和代码 示例输入:“艺术家:foo bar fooo标题:bar fooo bar尺寸:x z y框架尺寸:y z x”(如您所见,有“尺寸”和“框架尺寸”) 输出错误:{Artist:=foo bar fooo,Title:=bar fooo bar,维度:=x z y,维度:=y z x}(框架
“艺术家:foo bar fooo标题:bar fooo bar尺寸:x z y框架尺寸:y z x”
(如您所见,有“尺寸”和“框架尺寸”)
输出错误:{Artist:=foo bar fooo,Title:=bar fooo bar,维度:=x z y,维度:=y z x}
(框架维度在维度下被捕获!)
预期输出:Artist:=foo-bar-fooo,Title:=bar-fooo-bar,尺寸:=x-z-y,框架尺寸:=y-z-x}
代码示例:
String DELIMITER = "[Aa]rtist:|[Tt]itle:|[Ff]ramed [Dd]imensions:|[Dd]imensions:"
...
public Map<String, String> parseToMap(String str) {
Map<String, String> itemMap = new LinkedHashMap<>();
String infos[] = str.split("(?=" + DELIMITER + ')'); //split at delimiters
for(String info : infos) {
try {
String[] tmp = info.split("(?<=" + DELIMITER + ')'); //split to key/val pair
itemMap.put(tmp[0].trim(), tmp[1].trim());
} catch (IndexOutOfBoundsException e) {
//Skip if no key/val pair
}
}
return itemMap;
}
String DELIMITER=“[Aa]rtist:|[Tt]itle:|[Ff]ramed[Dd]维度:|[Dd]维度:”
...
公共映射解析映射(字符串str){
Map itemMap=newlinkedhashmap();
String infos[]=str.split((?=“+分隔符+”);//在分隔符处拆分
用于(字符串信息:infos){
试一试{
String[]tmp=info.split((?而不是split
操作将此正则表达式与两个捕获的组一起使用:
(?<key>[\w\s]+:)\s*(?<value>.+?)\s*(?=(?:[Aa]rtist|[Tt]itle|(?:[Ff]ramed )?[Dd]imensions):|$)
(?[\w\s]+:)\s*(?。+)\s*(?=(?:[Aa]rtist |[Tt]itle |)(?:[Ff]ramed)?[Dd]维度:|$)
代码:
final String regex = "(?<key>[\\w\\s]+:)\\s*(?<value>.+?)\\s*(?=(?:[Aa]rtist|[Tt]itle|(?:[Ff]ramed )?[Dd]imensions):|$)";
final String string = "Artist: foo Title: bar Dimensions: x Framed dimensions: y";
final Pattern pattern = Pattern.compile(regex);
final Matcher m = pattern.matcher(string);
Map<String, String> itemMap = new LinkedHashMap<>();
while (m.find()) {
itemMap.put(m.group("key"), m.group("value"));
}
System.out.println("itemMap: " + itemMap);
final String regex=“(?[\\w\\s]+:)\\s*(?。+?)\\s*(?=(?:[Aa]rtist|[Tt]itle |)(?:[Ff]ramed)?[Dd]维度):|$”;
final String=“艺术家:foo标题:条形尺寸:x框架尺寸:y”;
最终模式=Pattern.compile(regex);
最终匹配器m=模式匹配器(字符串);
Map itemMap=newlinkedhashmap();
while(m.find()){
itemMap.put(m.group(“key”)、m.group(“value”);
}
System.out.println(“itemMap:+itemMap”);
而不是拆分
操作将此正则表达式与两个捕获的组一起使用:
(?<key>[\w\s]+:)\s*(?<value>.+?)\s*(?=(?:[Aa]rtist|[Tt]itle|(?:[Ff]ramed )?[Dd]imensions):|$)
(?[\w\s]+:)\s*(?。+)\s*(?=(?:[Aa]rtist |[Tt]itle |)(?:[Ff]ramed)?[Dd]维度:|$)
代码:
final String regex = "(?<key>[\\w\\s]+:)\\s*(?<value>.+?)\\s*(?=(?:[Aa]rtist|[Tt]itle|(?:[Ff]ramed )?[Dd]imensions):|$)";
final String string = "Artist: foo Title: bar Dimensions: x Framed dimensions: y";
final Pattern pattern = Pattern.compile(regex);
final Matcher m = pattern.matcher(string);
Map<String, String> itemMap = new LinkedHashMap<>();
while (m.find()) {
itemMap.put(m.group("key"), m.group("value"));
}
System.out.println("itemMap: " + itemMap);
final String regex=“(?[\\w\\s]+:)\\s*(?。+?)\\s*(?=(?:[Aa]rtist|[Tt]itle |)(?:[Ff]ramed)?[Dd]维度):|$”;
final String=“艺术家:foo标题:条形尺寸:x框架尺寸:y”;
最终模式=Pattern.compile(regex);
最终匹配器m=模式匹配器(字符串);
Map itemMap=newlinkedhashmap();
while(m.find()){
itemMap.put(m.group(“key”)、m.group(“value”);
}
System.out.println(“itemMap:+itemMap”);
您的正则表达式是一个非消耗性的正向前瞻,它测试字符串中的每个位置,因此,它可以匹配重叠的字符串
您可以使用匹配方法将分隔符捕获到组1中,然后捕获未启动任何分隔符的任何字符:
public static Map<String, String> parseToMap(String str) {
String DESCRIPTION_DELIMITER = "[Aa]rtist:|[Tt]itle:|[Ff]ramed [Dd]imensions:|[Dd]imensions:";
Map<String, String> itemMap = new LinkedHashMap<>();
Pattern p = Pattern.compile("(" + DESCRIPTION_DELIMITER + ")((?:(?!" + DESCRIPTION_DELIMITER + ").)*)"); //split to key/val pair
Matcher m = p.matcher(str);
while(m.find()) {
itemMap.put(m.group(1).trim(), m.group(2).trim());
}
return itemMap;
}
看
这里,
([Aa]rtist:|[Tt]itle:|[Ff]ramed[Dd]维度:|[Dd]维度:)
-组1匹配任何分隔符
((?:(?![Aa]rtist:|[Tt]itle:|[Ff]ramed[Dd]dimensions:|[Dd]dimensions:)*)
-匹配除换行符(
)以外的任何字符,不启动任何分隔符字符序列的0+次(*
)
您的正则表达式是一个非消耗性的正向前瞻,它测试字符串中的每个位置,因此,它可以匹配重叠的字符串
您可以使用匹配方法将分隔符捕获到组1中,然后捕获未启动任何分隔符的任何字符:
public static Map<String, String> parseToMap(String str) {
String DESCRIPTION_DELIMITER = "[Aa]rtist:|[Tt]itle:|[Ff]ramed [Dd]imensions:|[Dd]imensions:";
Map<String, String> itemMap = new LinkedHashMap<>();
Pattern p = Pattern.compile("(" + DESCRIPTION_DELIMITER + ")((?:(?!" + DESCRIPTION_DELIMITER + ").)*)"); //split to key/val pair
Matcher m = p.matcher(str);
while(m.find()) {
itemMap.put(m.group(1).trim(), m.group(2).trim());
}
return itemMap;
}
看
这里,
([Aa]rtist:|[Tt]itle:|[Ff]ramed[Dd]维度:|[Dd]维度:)
-组1匹配任何分隔符
((?:(?![Aa]rtist:|[Tt]itle:|[Ff]ramed[Dd]dimensions:|[Dd]dimensions:)*)
-匹配除换行符(
)以外的任何字符,不启动任何分隔符字符序列的0+次(*
)
如果预期输入始终采用以下格式
艺术家:foo标题:条形尺寸:x框架尺寸:y
i、 e,“D”在维度上始终是大写,
你可以用
字符串分隔符=“[Aa]rtist:|[Tt]itle:|[Ff]ramed[Dd]维度:|维度:”;
而不是
String DELIMITER=“[Aa]rtist:|[Tt]itle:|[Ff]ramed[Dd]维度:|[Dd]维度:”如果预期输入始终采用以下格式
艺术家:foo标题:条形尺寸:x框架尺寸:y
i、 e,“D”在维度上始终是大写,
你可以用
字符串分隔符=“[Aa]rtist:|[Tt]itle:|[Ff]ramed[Dd]维度:|维度:”;
而不是
字符串分隔符=“[Aa]rtist:|[Tt]itle:|[Ff]框架[Dd]维度:|[Dd]维度:"在预期中,它不应该是Title:=bar
而不是Title=bar
?你完全正确,谢谢你抓住了我的打字错误!请看@WiktorStribiżew,你的解决方案对我很有效。想回答这个问题,我会接受它吗?在预期中,它不应该是Title:=bar
而不是Title=bar
?你完全正确谢谢你抓住我的打字错误!请看@WiktorStribiżew,你的解决方案对我有效。想回答这个问题,我会接受吗?这只得到下面的单词。我需要每个单词直到下一个分隔符。这只得到下面的单词。我需要每个单词直到下一个分隔符。