鉴于用户只能以特定格式输入值,我需要将该字符串的相关部分提取到 Java 变量中。
例如,可接受的格式是:-
String types[] = {"The quick brown ${animal} jumped over the lazy ${target}.",
"${target} loves ${animal}.",
"${animal} became friends with ${target}"};
变量:-
private String animal;
private String target;
现在,如果用户输入"The quick brown fox jumped over the lazy dog."
,动物变量应设置为"fox"
,目标变量应设置为"dog"
。
如果用户输入与给定类型都不匹配,则应显示错误。
基本上,我试图做org.apache.commons.lang.text.StrSubstitutor
所做的事情的反面。
我的方法(看起来效率低下,因此寻求帮助(:-
创建正则表达式模式以找出输入字符串的类型,然后为每个类型编写不同的逻辑。例如,对于第一种类型,获取单词"brown"后面的单词并将其分配给变量animal
依此类推。
使用@Josh Withee的答案:-
/**
* @param input String from which values need to be extracted
* @param templates Valid regex patterns with capturing groups
* @param variableNames Names for named capturing groups
* @return Map with variableNames as the keys and the extracted strings as map values
* OR an empty, non-null map if the input doesn't match with any template, or if there is no group with the given variableNames
*/
public static Map<String, String> extractVariablesFromString(String input, List<String> templates, String... variableNames) {
Map<String, String> resultMap = new HashMap<>();
Optional<String> matchedTemplate = templates.stream().filter(input::matches).findFirst();
matchedTemplate.ifPresent(t -> {
Matcher m = Pattern.compile(t).matcher(input);
m.find();
Arrays.stream(variableNames)
.forEach(v -> {
try {
resultMap.put(v, m.group(v));
} catch (IllegalArgumentException e) {
}
});
});
return resultMap;
}
测试:-
@Test
public void shouldExtractVariablesFromString() {
String input = "The quick brown fox jumped over the lazy dog.";
String types[] = {"The quick brown (?<animal>.*) jumped over the lazy (?<target>.*).",
"(?<target>.*) loves (?<animal>.*).",
"(?<animal>.*) became friends with (?<target>.*)"};
Map<String, String> resultMap = StringUtils.extractVariablesFromString(input, Arrays.asList(types), "animal", "target1", "target");
Assert.assertEquals("fox", resultMap.get("animal"));
Assert.assertEquals("dog", resultMap.get("target"));
Assert.assertFalse(resultMap.containsKey("target1"));
}
@Test
public void shouldReturnEmptyMapIfInputDoesntMatchAnyPatternForVariableExtraction() {
String input = "The brown fox passed under the lazy dog.";
String types[] = {"The quick brown (?<animal>.*) jumped over the lazy (?<target>.*).",
"(?<animal>.*) became friends with (?<target>.*)"};
Map<String, String> resultMap = StringUtils.extractVariablesFromString(input, Arrays.asList(types), "animal", "target1", "target");
Assert.assertTrue(resultMap.isEmpty());
}
可以使用命名的捕获组执行此操作:
String userInput = "dog loves fox.";
String types[] = {"The quick brown (?<animal>.*?) jumped over the lazy (?<target>.*?).",
"(?<target>.*?) loves (?<animal>.*?).",
"(?<animal>.*?) became friends with (?<target>.*?)"};
Matcher m;
for(int i=0; i<types.length(); i++;){
if(userInput.matches(types[i]){
m = Pattern.compile(types[i]).matcher(userInput);
break;
}
}
m.find();
String animal = m.group("animal");
String target = m.group("target");
/**
*
* @param input /Volumes/data/tmp/send/20999999/sx/0000000110-0000000051-007-20211207-01.txt
* @param template /{baseDir}/send/{yyyyMMdd}/{organization}/{sendOrganization}-{receiveOrganization}-{fileType}-{date}-{batch}.txt
* @param prefix
* @param suffix
* @return
*/
public static Map<String, String> extractVariables(final String input, final String template, final String prefix, final String suffix) {
final HashSet<String> variableNames = new HashSet<>();
String variableNamesRegex = "(" + prefix + "([^" + prefix + suffix + "]+?)" + suffix + ")";
Pattern variableNamesPattern = Pattern.compile(variableNamesRegex);
Matcher variableNamesMatcher = variableNamesPattern.matcher(template);
while (variableNamesMatcher.find()) {
variableNames.add(variableNamesMatcher.group(2));
}
final String regexTemplate = template.replaceAll(prefix, "(?<").replaceAll(suffix, ">.*)");
Map<String, String> resultMap = new HashMap<>();
Matcher matcher = Pattern.compile(regexTemplate).matcher(input);
matcher.find();
variableNames.forEach(v -> resultMap.put(v, matcher.group(v)));
return resultMap;
}
用法像
extractVariables(input, template2, "\{", "\}"(