Я пытаюсь использовать регулярное выражение для извлечения выражений в формате «операнд оператора-операнда» из входной строки. Операндами могут быть любые отдельные слова или фразы в кавычках, а оператор между операндами будет знаком тильды, за которым следует цифра. Выражение может встречаться n раз в строке ввода. Что не так в моем регулярном выражении?
package test;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ExpressionExtractor {
private static final String operator = "\\s+\\~{1}\\d+\\s+";
private static final String quotedWords = "[\"|'|“][A-Za-zÀ-ü0-9\\\\.\\/\\-,\\*\\s]+[\"|'|“]";
private static final String singleWords = "[A-Za-zÀ-ü0-9\\\\.\\/\\-,\\*]+";
private static final String operand = quotedWords+"|"+singleWords;
private static final Pattern expressionPattern = Pattern.compile("("+operand + operator +operand+")");
private static final Pattern operatorPattern = Pattern.compile(operator);
public static Matcher evaluateExpression(String input) {
return expressionPattern.matcher(input);
}
}
Тестовый пример с ожидаемыми результатами:
package test;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import org.junit.Test;
public class ExpressionExtractorUnitTest {
@Test
public void testExpressionExtractor() {
assertEquals(Arrays.asList("firstWord ~20 secondWord"), find("any word firstWord ~20 secondWord one more word"));
assertEquals(Arrays.asList("mother-in-law ~8 long-Word"), find("start of sentence mother-in-law ~8 long-Word one sentence"));
assertEquals(Arrays.asList("firstWord ~7 secondWord", "word ~8 \"complex expression\""),
find("more complex expression firstWord ~7 secondWord with another word ~8 \"complex expression\" continued"));
}
private List<String> find(String expression) {
Matcher matcher = ExpressionExtractor.evaluateExpression(expression);
List<String> tokens = new ArrayList<>();
while (matcher.find()) {
tokens.add(matcher.group());
}
return tokens;
}
}