Регулярное выражение для последовательных повторяющихся слов - PullRequest
97 голосов
/ 13 мая 2010

Я новичок в регулярных выражениях, и я не могу понять, как написать одно регулярное выражение, которое бы "соответствовало" любым повторяющимся последовательным словам, таким как:

Париж в Весне .

Не что это связано.

Почему ты смеешься? my my регулярные выражения, что плохо ??

Существует ли единственное регулярное выражение, которое будет соответствовать ВСЕМ жирным строкам выше?

Ответы [ 13 ]

116 голосов
/ 13 мая 2010

Попробуйте это регулярное выражение:

\b(\w+)\s+\1\b

Здесь \b - граница слова, а \1 ссылается на захваченное совпадение первой группы.

18 голосов
/ 07 сентября 2012

Я считаю, что это регулярное выражение обрабатывает больше ситуаций:

/(\b\S+\b)\s+\b\1\b/

Хороший выбор тестовых строк можно найти здесь: http://callumacrae.github.com/regex-tuesday/challenge1.html

5 голосов
/ 05 июня 2017

Попробуйте это ниже RE

  • \ b начало слова границы слова
  • \ W + любой символ слова
  • \ 1 одно и то же слово уже найдено
  • \ b конец слова
  • () * Повторение еще раз

    public static void main(String[] args) {
    
        String regex = "\\b(\\w+)(\\b\\W+\\b\\1\\b)*";//  "/* Write a RegEx matching repeated words here. */";
        Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE/* Insert the correct Pattern flag here.*/);
    
        Scanner in = new Scanner(System.in);
    
        int numSentences = Integer.parseInt(in.nextLine());
    
        while (numSentences-- > 0) {
            String input = in.nextLine();
    
            Matcher m = p.matcher(input);
    
            // Check for subsequences of input that match the compiled pattern
            while (m.find()) {
                input = input.replaceAll(m.group(0),m.group(1));
            }
    
            // Prints the modified sentence.
            System.out.println(input);
        }
    
        in.close();
    }
    
5 голосов
/ 13 мая 2010

Широко используемая библиотека PCRE может справиться с такими ситуациями (однако вы не достигнете того же с POSIX-совместимыми механизмами регулярных выражений):

(\b\w+\b)\W+\1
3 голосов
/ 24 марта 2018

Вот тот, который ловит несколько слов несколько раз:

(\b\w+\b)(\s+\1)+
3 голосов
/ 13 мая 2010

Нет. Это неправильная грамматика. Вы можете использовать регулярные выражения, специфичные для движка / языка, но вы не можете использовать универсальное регулярное выражение.

2 голосов
/ 18 июля 2015

Это регулярное выражение, которое я использую для удаления повторяющихся фраз в моем боте дергания:

(\S+\s*)\1{2,}

(\S+\s*) ищет любую строку символов, которая не является пробелом, а затем пробел.

\1{2,} затем ищет более 2 экземпляров этой фразы в строке для сопоставления. Если есть 3 фразы, которые совпадают, это соответствует.

2 голосов
/ 25 апреля 2013

Пример в Javascript: Хорошие части могут быть адаптированы для этого:

var doubled_words = /([A-Za-z\u00C0-\u1FFF\u2800-\uFFFD]+)\s+\1(?:\s|$)/gi;

\ b использует \ w для границ слова, где \ w эквивалентно [0-9A-Z_a-z]. Если вы не возражаете против этого ограничения, принятый ответ - в порядке.

1 голос
/ 01 февраля 2018

Поскольку некоторые разработчики заходят на эту страницу в поисках решения, которое не только устраняет дубликаты последовательных непробельных подстрок, но и повторяет их и так далее, я покажу адаптированный шаблон.

Pattern: /(\b\S+)(?:\s+\1\b)+/ ( Pattern Demo )
Заменить: $1 (заменяет совпадение полной строки с группой захвата # 1)

Этот шаблон жадно сопоставляет «целую» подстроку без пробелов, затем требуется одна или несколько копий совпадающей подстроки, которая может быть разделена одним или несколькими пробельными символами (пробел, табуляция, символ новой строки и т. Д.).

В частности:

  • \b (граница слова) символы необходимы для обеспечения того, чтобы частичные слова не совпадали.
  • Вторая скобка - это группа без захвата, потому что эту подстроку переменной ширины не нужно захватывать - только сопоставлять / поглощать.
  • + (один или несколько квантификаторов) в группе без захвата является более подходящим, чем *, потому что * будет "беспокоить" механизм регулярных выражений для захвата и замены одноэлементных вхождений - это расточительный дизайн шаблона .

* обратите внимание, если вы имеете дело с предложениями или входными строками с пунктуацией, шаблон необходимо будет доработать.

1 голос
/ 18 февраля 2016

Это выражение (вдохновленное Майком, выше), кажется, улавливает все дубликаты, тройки и т. Д., Включая те, что находятся в конце строки, чего большинство других не делает:

/(^|\s+)(\S+)(($|\s+)\2)+/g, "$1$2")

Я знаю, что вопрос задан для совпадения только дубликаты , но триплет - это просто 2 дубликата рядом друг с другом:)

Во-первых, я ставлю (^|\s+), чтобы убедиться, что он начинается с полного слова, в противном случае «детский стейк» переходит к «детский стейк» («s» соответствует). Затем он сопоставляет все полные слова ((\b\S+\b)), за которыми следует конец строки ($) или количество пробелов (\s+), причем целое повторяется более одного раза.

Я попробовал это так, и это сработало:

var s = "here here here     here is ahi-ahi ahi-ahi ahi-ahi joe's joe's joe's joe's joe's the result result     result";
print( s.replace( /(\b\S+\b)(($|\s+)\1)+/g, "$1"))         
--> here is ahi-ahi joe's the result
...