从String中提取变量值

问题描述 投票:0回答:2

鉴于用户只能以特定格式输入值,我需要将该字符串的相关部分提取到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,依此类推。

java regex string
2个回答
0
投票

您可以使用命名捕获组执行此操作:

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");

0
投票

使用@ Marathon55的答案: -

/**
 * @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());
    }
© www.soinside.com 2019 - 2024. All rights reserved.