Строка, захваченная рекурсией регулярного выражения

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

У меня есть это регулярное выражение:

(?<domain>\w+\.\w+)($|\/|\.)

И я хочу рекурсивно захватить каждый субдомен. Например, в этой строке:

test1.test2.abc.def

Это выражение захватывает test1.test2 и abc.def, но мне нужно захватить: test1.test2 test2.abc abc.def

Знаете ли вы, есть ли возможность сделать это рекурсивно?

Спасибо!


person Dugalle    schedule 20.02.2020    source источник
comment
Какой аромат регулярного выражения вы используете? Некоторые поддерживают рекурсивное сопоставление.   -  person Schwern    schedule 20.02.2020
comment
Итак, вы говорите, что регулярное выражение может сопоставлять текст, который не принадлежит этому тексту, в первую очередь @Schwern?   -  person Themelis    schedule 20.02.2020
comment
Обратите внимание, что имена доменов включают - и исключают _. [a-zA-Z0-9-] является лучшим приближением. См. этот ответ для правильного регулярного выражения. stackoverflow.com/questions/60269926/   -  person Schwern    schedule 20.02.2020
comment
@Themelis Я думаю, что (?R) может быть полезным. Не уверен, что вы имеете в виду.   -  person Schwern    schedule 20.02.2020
comment
У тебя было время проверить мое предложение? Предложения других? У вас что-нибудь получилось?   -  person Wiktor Stribiżew    schedule 21.02.2020


Ответы (3)


Вы можете использовать известный метод извлечения перекрывающихся совпадений , но вы не можете полагаться на границы \b, поскольку они могут совпадать между символом без слова/слова и символом слова/не слова. Вам нужны однозначные границы слов для левого и правого контекстов.

Использовать

(?=(?<!\w)(?<domain>\w+\.\w+)(?!\w))

См. демонстрацию регулярного выражения. Подробности:

  • (?= - a positive lookahead that enables testing each location in the string and capture the part of string to the right of it
    • (?<!\w) - a left-hand side word boundary
    • (?<domain>\w+\.\w+) - Группа "домен": 1+ словесных символов, . и 1+ словесных символов
    • (?!\w) - правая граница слова
  • ) - конец внешнего просмотра вперед.

Другой подход заключается в использовании точек в качестве разделителей слов. Затем используйте

(?=(?<![^.])(?<domain>[^.]+\.[^.]+)(?![^.]))

См. эту демонстрацию регулярного выражения. Отрегулируйте, как считаете нужным.

person Wiktor Stribiżew    schedule 20.02.2020

Возможно, следует:

(\.|^)(?=(\w+\.\w+))

Перейти с группой захвата 2

person JvdV    schedule 20.02.2020

Вы можете использовать положительный взгляд вперед, чтобы захватить следующую группу.

/(\w+)\.(?=(\w+))/g

Демонстрация.

Изменить: регулярное выражение JvdV более правильно.


Обратите внимание, что \w+ не будет соответствовать доменам, таким как regex-tester.com, и будет соответствовать недействительному regex_tester.com. [a-zA-Z0-9-]+ ближе к правильному. Полное регулярное выражение см. в этом ответе.


Проще и надежнее сделать это, разбивая на . и перебирая части попарно. Например, в Руби...

"test1.test2.abc.def".split(".").each_cons(2) { |a|
  puts a.join(".")
}

test1.test2
test2.abc
abc.def
person Schwern    schedule 20.02.2020