Есть ли метод API, который возвращает все (возможно перекрывающиеся) подстроки, которые соответствуют регулярному выражению?Все перекрывающиеся подстроки, соответствующие регулярному выражению java
Например, у меня есть текстовая строка: String t = 04/31 412-555-1235;
, и у меня есть шаблон: Pattern p = new Pattern("\\d\\d+");
, который соответствует строкам двух или более символов.
Спички я получаю: 04, 31, 412, 555, 1235.
Как получить перекрывающихся матчи?
Я хочу код возврата: 04, 31, 41, 412, 12, 55, 555, 55, 12, 123, 1235, 23, 235, 35.
Теоретически это должно быть возможным - существует очевидный алгоритм O(n^2)
, который перечисляет и проверяет все подстроки по шаблону.
EDIT
Вместо перечисления всех подстрок, безопаснее использовать метод region(int start, int end)
в Matcher
. Проверка шаблона на отдельную извлеченную подстроку может изменить результат совпадения (например, если в начале/конце шаблона есть негравифицирующая группа или проверка границы слов).
EDIT 2
На самом деле, неясно, имеет ли region()
, что вы ожидаете для нулевой ширины спичек. Спецификация является неопределенной, и эксперименты дают неутешительные результаты.
Например:
String line = "xx90xx";
String pat = "\\b90\\b";
System.out.println(Pattern.compile(pat).matcher(line).find()); // prints false
for (int i = 0; i < line.length(); ++i) {
for (int j = i + 1; j <= line.length(); ++j) {
Matcher m = Pattern.compile(pat).matcher(line).region(i, j);
if (m.find() && m.group().size == (j - i)) {
System.out.println(m.group() + " (" + i + ", " + j + ")"); // prints 90 (2, 4)
}
}
}
Я не уверен, что самое элегантное решение. Один из подходов состоял бы в том, чтобы взять подстроку line
и проложить с соответствующими символами границы, прежде чем проверять соответствие совпадений pat
.
EDIT 3
Вот полное решение, что я придумал. Он может обрабатывать шаблоны нулевой ширины, границы и т. Д. В исходном регулярном выражении. Он просматривает все подстроки текстовой строки и проверяет, соответствует ли регулярное выражение только в конкретной позиции, заполняя шаблон соответствующим количеством подстановочных знаков в начале и конце. Кажется, что я работаю над случаями, которые я пробовал, хотя я не проводил тщательного тестирования. Это, безусловно, менее эффективно, чем могло бы быть.
public static void allMatches(String text, String regex)
{
for (int i = 0; i < text.length(); ++i) {
for (int j = i + 1; j <= text.length(); ++j) {
String positionSpecificPattern = "((?<=^.{"+i+"})("+regex+")(?=.{"+(text.length() - j)+"}$))";
Matcher m = Pattern.compile(positionSpecificPattern).matcher(text);
if (m.find())
{
System.out.println("Match found: \"" + (m.group()) + "\" at position [" + i + ", " + j + ")");
}
}
}
}
EDIT 4
Вот лучший способ сделать это: https://stackoverflow.com/a/11372670/244526
EDIT 5
JRegex библиотека поддерживает поиск всех перекрывающихся подстроки совпадающие с Java регулярное выражение (хотя он, похоже, не обновлялся в то время).В частности, documentation on non-breaking search указует:
Использования неразрывного поиска вы можете найти все возможное occureneces из в модели, в том числе тех, которые пересекаются или вложенными. Это , достигнутый с использованием метода Matcher.()
просто сделайте повторное регулярное повторение после всех трех и более символов. –
http://regexlib.com/ может быть хорошим местом для некоторых рытьев. –
@ Ωmega Попытайтесь изо всех сил, но откройте для обратной связи, что не полезно. Приветствия. –