从字符串中提取变量值



鉴于用户只能以特定格式输入值,我需要将该字符串的相关部分提取到 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, "\{", "\}"(

最新更新