问题描述
给定两个字符串
String command = "Header '{1}' has a value that ends with '{2}' (ignore case)";
String input = "Header 'some-value' has a value that ends with '123ws' (ignore case)";
我想获取价值地图。
0 -> some-value
1 -> 123ws
我引用了 this answer on Java Comparing two strings with placeholder values,根据我的使用情况稍微调整了它。
private static Map<Integer,Object> getUserInputMap(String command,String input) {
System.out.println("\t" + command);
System.out.println("\t" + input);
command = command.replace("(","<");
command = command.replace(")",">");
input = input.replace("(","<");
input = input.replace(")",">");
Map<Integer,Object> userInputMap = new HashMap<>();
String patternTemplate = command.replace("{0}","(.*)");
patternTemplate = patternTemplate.replace("{1}","(.*)");
patternTemplate = patternTemplate.replace("{2}","(.*)");
Pattern pattern = Pattern.compile(patternTemplate);
Matcher matcher = pattern.matcher(input);
if (matcher.matches()) {
for (int gi = 1; gi <= matcher.groupCount(); gi++) {
String uin = matcher.group(gi);
uin = uin.replace("<","(");
uin = uin.replace(">",")");
userInputMap.put(gi - 1,uin);
}
}
return userInputMap;
}
但是,可能有很多极端情况。我担心我的解决方案是我可能会错过一个角落案例,然后是生产错误。
是否有围绕此编写的成熟库?我正在检查 messageformat/StrSubstitutor,但我无法获得任何符合我预期的方法。
解决方法
从已经格式化的字符串中获取除字符串以外的任何内容并不容易,我不会在这里处理。
您基本上知道占位符的格式,即 {digits}
,因此您可以通过以下方式拆分命令:command.split("\\{0|[1-9][0-9]*\\}"
(不允许 {01}
等)。
然后遍历结果数组中的元素并在 input
中查找完全匹配。执行此操作时,您希望跟踪结束索引以从那里开始搜索,而不是再次从 input
开始。
快速简单的示例(未测试):
String[] parts = command.split("\\{0|[1-9][0-9]*\\}");
int paramStart = 0;
int index = 0;
for( String part : parts ) {
index = input.indexOf(part,index);
if( index < 0) {
//problem: command part hasn't been found - you probably want to end parsing here
}
//the first part should be found at index 0 so ignore that
if( index != 0 )
//parameter value should be between the last part and the current one
String parameterValue = input.substring(paramStart,index);
}
//the next parameter starts after the current part
paramStart= index + part.length();
}
//there seems to be a last placeholder at the end of the command
if(paramStart < input.length() - 1) {
//get the substring here
}
这应该能够处理大多数情况,除了参数看起来像命令部分或占位符彼此相邻且无法区分的情况。以 "{1} - {2}"
和参数 "A - B"
和 "C - D"
为例 - 结果将是 "A - B - C - D"
,在这种情况下,如果没有更多参数,您将无法安全地确定这两个参数的值信息(您没有仅占位符的信息)。