[英]Java regex - replace substrings between delimiters with same substrings without delimiters
[英]Java regex split on multiple delimiters including substrings of other delimiters
我正在尝试使用正则表达式和已知的定界符将字符串转换为值映射。 我拥有的代码可以工作,但是如果我使用的分隔符是另一个分隔符的子字符串,则不会(正确)对其进行解析。
让我们直接切入一些样本输入,错误输出,预期输出和代码!
输入示例: "Artist: foo bar foooo Title: bar fooo bar Dimensions: xzy Framed dimensions: yzx"
(您可以看到有“ Dimensions”和“ Framed Dimensions”)
错误输出: {Artist:=foo bar foooo, Title:=bar fooo bar, Dimensions:=xzy, dimensions:=yzx}
(框架尺寸被尺寸吸引!)
预期输出: Artist:=foo bar foooo, Title:=bar fooo bar, Dimensions:=xzy, Framed dimensions:=yzx}
代码示例:
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;
}
我也觉得这有点骇人听闻。 如果有更好的解决方案,我很高兴听到。 尽管如果我们现在就可以使它正常运行,我总是可以去CodeReview看看:)
编辑:我需要从定界符到定界符的每个单词,而不仅仅是定界符之后的单词。
而不是split
操作,请将此正则表达式与2个捕获的组一起使用:
(?<key>[\w\s]+:)\s*(?<value>.+?)\s*(?=(?:[Aa]rtist|[Tt]itle|(?:[Ff]ramed )?[Dd]imensions):|$)
码:
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);
您的正则表达式是一种非消耗性的正向超前行为,它可以测试字符串中的每个位置,因此可以匹配重叠的字符串。
您可以使用匹配方法将定界符捕获到组1中,然后将任何不启动任何定界符的char捕获:
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;
}
请参阅Java演示 。
正则表达式看起来像
([Aa]rtist:|[Tt]itle:|[Ff]ramed [Dd]imensions:|[Dd]imensions:)((?:(?![Aa]rtist:|[Tt]itle:|[Ff]ramed [Dd]imensions:|[Dd]imensions:).)*)
请参阅在线演示 。
这里,
([Aa]rtist:|[Tt]itle:|[Ff]ramed [Dd]imensions:|[Dd]imensions:)
-与任何定界符匹配的第1组 ((?:(?![Aa]rtist:|[Tt]itle:|[Ff]ramed [Dd]imensions:|[Dd]imensions:).)*)
-与除a以外的任何char匹配的钢化贪婪令牌换行符char( .
),出现0+次( *
),不会开始任何分隔符字符序列。 如果期望输入始终为以下格式
艺术家:foo标题:bar尺寸:x框架尺寸:y
即,“ D”始终是维度中的大写字母,您可以使用String DELIMITER =“ [Aa] rtist:| [Tt] itle:| [Ff] ramed [Dd] imensions:| Dimensions:”; 而不是字符串DELIMITER =“ [Aa] rtist:| [Tt] itle:| [Ff] ramed [Dd] imensions:| [Dd] imensions:”
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.