Регулярные выражения положительный просмотр назад + отрицательный просмотр вперед

Учитывая строку "A B C a b B", я хочу сопоставить повторяющиеся слова (независимо от регистра). Ожидаемый результат будет соответствовать "a" и "b" (последние вхождения A и B) ИЛИ "A" и "B" (первые вхождения)

EDIT: я хочу найти только первое или последнее вхождение слова

Я знаю, что на этот вопрос можно было бы лучше ответить, разбив строку и подсчитав каждый токен (уменьшив регистр).
Однако я хотел бы попытаться сформулировать регулярное выражение, которое поможет мне найти эти слова, просто ради практики. .

Моя первая попытка была: (?=\b(\w+)\b.*\b(\1)\b)(\1)
Однако она соответствует первому A, первому B и второму b (A B b).

Я думал каким-то образом использовать положительный просмотр с отрицательным просмотром вперед, чтобы получить последние экземпляры повторяющегося слова: (?<=.*(?!.*(\w+).*)\1.*)\b\1\b
(в моей голове это переводится как «слово, которое было сопоставлено раньше и больше не будет соответствовать ")

Ну, это не работает для меня, к сожалению.

Можно ли таким образом использовать положительный и отрицательный просмотр вперед?
Можно ли исправить мое регулярное выражение?
Я пытался решить эту проблему на C#.

Это не домашнее задание


person Eugene Krapivin    schedule 10.07.2015    source источник


Ответы (1)


Интересная головоломка. Вот мое решение:

(\b\w+\b)(?:(?=.*?\b\1\b)|(?<=\b\1\b.*?\1))

Демо

Аргументация следующая:

  • Сопоставьте слово: (\b\w+\b)

  • Затем либо: (?:...|...)

    • Make sure it occurs again later on: (?=.*?\b\1\b)
    • Или это уже было раньше: (?<=\b\1\b.*?\1)

      Этот второй \1 в ретроспективном поиске соответствует слову, которое только что было найдено ранее. Первый \1 является реальным дубликатом.


Ответ на отредактированный вопрос:

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

(\b\w+\b)(?=.*?\b\1\b)(?<!\b\1\b.*?\1)

Демо

Теперь логика такая:

  • Сопоставьте слово: (\b\w+\b)
  • Убедитесь, что это повторяется снова: (?=.*?\b\1\b)
  • И убедитесь, что этого не произошло раньше: (?<!\b\1\b.*?\1)

    (то же самое, что и раньше, за исключением отрицательного взгляда назад)

person Lucas Trzesniewski    schedule 10.07.2015
comment
Я хочу сопоставить повторяющиеся слова только один раз. Я отредактировал вопрос. Извиняюсь. - person Eugene Krapivin; 11.07.2015
comment
@nocgod нет проблем, я расширил ответ - person Lucas Trzesniewski; 11.07.2015
comment
@Lucas_Trezsniewski Отлично! Я перемещал эти части, понятия не имею, почему я не попробовал простое решение! - person Eugene Krapivin; 11.07.2015