Как я могу выделить последовательные дублирующиеся слова с регулярным выражением Perl?

Я хочу регулярное выражение Perl, которое распознает дублированные слова в строке.

Учитывая следующий вход:

$str = "Thus joyful Troy Troy maintained the the watch of night..."

Я хотел бы следующий вывод:

Thus joyful [Troy Troy] maintained [the the] watch of night...
6
задан Shog9 24 March 2010 в 19:44
поделиться

3 ответа

Это работает:

$str =~ s/\b((\w+)\s+\2)\b/[\1]/g;
10
ответ дан 8 December 2019 в 04:52
поделиться

Это похоже на одно из упражнений Learning Perl . Уловка состоит в том, чтобы уловить все повторяющиеся слова, поэтому вам понадобится квантификатор «один или несколько» для дублирования:

 $str = 'This is Goethe the the the their sentence';

 $str =~ s/\b((\w+)(?:\s+\2\b)+)/[\1]/g;

Функции, которые я собираюсь использовать, описаны в perlre , когда они применяются в шаблоне или perlop , когда они влияют на то, как оператор подстановки выполняет свою работу.

Если вам нравится флаг / x для добавления несущественных пробелов и комментариев:

 $str =~ s/
      \b
      (
         (\w+)
         (?:
          \s+
          \2
          \b
         )+
      )
     /[\1]/xg;

Мне это не нравится \ 2 , потому что я ненавижу считать относительные позиции. Я могу использовать относительные обратные ссылки в Perl 5.10. \ g {-1} относится к непосредственно предшествующей группе захвата:

 use 5.010;
 $str =~ s/
      \b
      (
         (\w+)
         (?:
          \s+
          \g{-1}
          \b
         )+
      )
     /[\1]/xg;

Подсчет тоже не так уж хорош, поэтому я могу использовать помеченные совпадения:

 use 5.010;
 $str =~ s/
      \b
      (
         (?<word>\w+)
         (?:
          \s+
          \k<word>
          \b
         )+
      )
     /[\1]/xg;

Я могу пометить первый захват ( $ 1 ) и получить доступ к его значению в % + позже:

 use 5.010;
 $str =~ s/
      \b
      (?<dups>
         (?<word>\w+)
         (?:
          \s+
          \k<word>
          \b
         )+
      )
     /[$+{dups}]/xg;

Мне действительно не нужен этот первый захват, поскольку он действительно нужен только для ссылки на все, что соответствует. К сожалению, похоже, что $ {^ MATCH} не установлено достаточно рано, чтобы я мог использовать его в качестве замены. Я думаю, что это ошибка. Это должно работать, но не работает:

 $str =~ s/
      \b
         (?<word>\w+)
         (?:
          \s+
          \k<word>
          \b
         )+
     /[${^MATCH}]/pgx;   # DOESN'T WORK

Я проверяю это на blead, но это займет некоторое время, чтобы скомпилировать на моей крошечной машине.

12
ответ дан 8 December 2019 в 04:52
поделиться

Вы можете попробовать:

$str = "Thus joyful Troy Troy maintained the the watch of night...";
$str =~s{\b(\w+)\s+\1\b}{[$1 $1]}g;
print "$str"; # prints Thus joyful [Troy Troy] maintained [the the] watch of night...

Используемое регулярное выражение: \ b (\ w +) \ s + \ 1 \ b

Пояснение:

  • \ b : word bondary
  • \ w + : слово
  • () : запомнить указанное выше слово
  • \ s + : пробел
  • \ 1 : запомненное слово

Эффективно находит два полные слов, разделенных пробелом и помещающие вокруг них [] .

РЕДАКТИРОВАТЬ:

Если вы хотите сохранить количество пробелов между словами, которые вы можете использовать:

$str =~s{\b(\w+)(\s+)\1\b}{[$1$2$1]}g;
2
ответ дан 8 December 2019 в 04:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: