Как использовать Java Regex для поиска всех повторяющихся последовательностей символов в строке?

Разбор случайной строки, которая ищет повторяющиеся последовательности с использованием Java и Regex.

Рассмотрим строки:

aaabbaaacccbb

Я хотел бы найти регулярное выражение, которое найдет все совпадения в приведенной выше строке:

aaabbaaacccbb
^^^  ^^^

aaabbaaacccbb
   ^^      ^^

Что представляет собой выражение регулярного выражения, которое будет проверять строку для любых повторяющихся последовательностей символов и возвращать группы этих повторяющихся символов таким образом, что группа 1 = aaa и группа 2 = bb. Также обратите внимание, что я использовал примерную строку, но все повторяющиеся символы действительны: RonRonJoeJoe ......,,...,

Ответ 1

Это делает:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Test {
    public static void main(String[] args) {
        String s = "aaabbaaacccbb";
        find(s);
        String s1 = "RonRonRonJoeJoe .... ,,,,";
        find(s1);
        System.err.println("---");
        String s2 = "RonBobRonJoe";
        find(s2);
    }

    private static void find(String s) {
        Matcher m = Pattern.compile("(.+)\\1+").matcher(s);
        while (m.find()) {
            System.err.println(m.group());
        }
    }
}

ВЫВОД:

aaa
bb
aaa
ccc
bb
RonRonRon
JoeJoe
....
,,,,
---

Ответ 2

Ниже следует работать для всех требований. На самом деле это комбинация из нескольких ответов здесь, и она выведет все подстроки, которые повторяются в другом месте в строке.

Я установил его, чтобы возвращать подстроки не менее двух символов, но его можно легко изменить на отдельные символы, изменив "{2,}" в регулярном выражении на "+".

public static void main(String[] args)
{
  String s = "RonSamJoeJoeSamRon";
  Matcher m = Pattern.compile("(\\S{2,})(?=.*?\\1)").matcher(s);
  while (m.find())
  {
    for (int i = 1; i <= m.groupCount(); i++)
    {
      System.out.println(m.group(i));
    }
  }
}

Выход:
Рон
Сэм
Джо

Ответ 3

Вы можете использовать это регулярное выражение positive lookahead:

((\\w)\\2+)(?=.*\\1)

Код:

String elem = "aaabbaaacccbb";
String regex = "((\\w)\\2+)(?=.*\\1)";
Pattern p = Pattern.compile(regex);
Matcher matcher = p.matcher(elem);
for (int i=1; matcher.find(); i++)
System.out.println("Group # " + i + " got: " + matcher.group(1));

ВЫВОД:

Group # 1 got: aaa
Group # 2 got: bb

Ответ 4

Это похоже на работу, хотя и дает подпоследовательности:

(Чтобы быть справедливым, это было построено на основе кода Гийима)

public static void main(final String[] args) {
    // final String s = "RonRonJoeJoe";
    // final String s = "RonBobRonJoe";
    final String s = "aaabbaaacccbb";

    final Pattern p = Pattern.compile("(.+).*\\1");

    final Matcher m = p.matcher(s);
    int start = 0;
    while (m.find(start)) {
        System.out.println(m.group(1));
        start = m.toMatchResult().end(1);
    }
}

Ответ 5

Вы можете игнорировать совпадение.

// overlapped 1 or more chars
(?=(\w{1,}).*\1)
// overlapped 2 or more chars
(?=(\w{2,}).*\1)
// overlapped 3 or more chars, etc ..
(?=(\w{3,}).*\1)

Или вы могли бы потреблять (без перекрытия)..

// 1 or more chars
(?=(\w{1,}).*\1) \1
// 2 or more chars
(?=(\w{2,}).*\1) \1
// 3 or more chars, etc ..
(?=(\w{3,}).*\1) \1