Подтвердить что ты не робот

Групповой захват группы Notepad ++

У меня есть такой файл txt:

ххх.prontube.ru
salo.ru
bbb.antichat.ru
yyy.ru
xx.bb.prontube.ru
zzz.com
srfsf.jwbefw.com.ua

Попытка удалить все поддомены с таким регулярным выражением:

Find:    .+\.((.*?)\.(ru|ua|com\.ua|com|net|info))$
Replace with: \1

Прием:

prontube.ru
salo.ru
antichat.ru
yyy.ru
prontube.ru
zzz.com
com.ua

Почему последняя строка становится com.ua вместо jwbefw.com.ua?

4b9b3361

Ответ 1

Это работает без оглядки:

Найти: [a-zA-Z0-9-.]+\.([a-zA-Z0-9-]+)\.([a-zA-Z0-9-]+)$ Заменить: \1\.\2

Он находит что-то с по крайней мере 2 периодами и только буквы, цифры и тире после двух последних периодов; затем он заменяет его на последние 2 части. Более интуитивно, по-моему.

Что-то смешное происходит с этим ведущим xxx. Это не похоже на ASCII. Ради этого вопроса я собираюсь предположить, что что-то смешное с этим сайтом, а не репрезентативными вашими реальными данными.

Некорректное

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

Найти: [a-zA-Z0-9-]+\.([a-zA-Z0-9-]+)\.(.+)$ Заменить: \1\.\2

Он просто находит имя хоста с не менее чем двумя периодами в нем, а затем заменяет его всем после первой точки.

Ответ 2

Часть .+ соответствует как можно больше. Попробуйте вместо этого использовать .+?, и он будет отображать как можно меньше, позволяя опции com.ua соответствовать.

Ответ 3

.+?\.([\w-]*?\.(?:ru|ua|com\.ua|com|net|info))$

В этом ответе по-прежнему используются конкретные доменные имена, которые рассматривал исходный вопрос. Поскольку некоторые TLD (домены верхнего уровня) имеют период в них, и теоретически у вас может быть список, включающий несколько поддоменов, белый список TLD в регулярном выражении является хорошей идеей, если он работает с вашим набором данных. Оба текущих ответа (с 2013 года) не будут корректно обрабатывать разницу между "xx.bb.prontube.ru" и "srfsf.jwbefw.com.ua".

Вот краткое объяснение того, почему это оригинальное регулярное выражение psnig не работает должным образом:
+ жадный. .+ в конце строки пронесется вправо, захватывая все, затем двигайтесь назад (влево) в поисках совпадения:

(ru|ua|com\.ua|com|net|info)

С srfsf.jwbefw.com.ua механизм регулярных выражений сначала не сможет соответствовать a, тогда он переместит токен на одно место влево, чтобы посмотреть на "ua" В этот момент ua из регулярного выражения (второй вариант) является совпадением.

Движок не будет искать "com.ua", потому что ".ua" соответствует этому требованию.

Ответ Niet the Dark Absol говорит регулярному выражению "ленивый"
.+? будет соответствовать любому персонажу (по крайней мере, одному), а затем попытаться найти следующую часть регулярного выражения. Если это не удастся, он будет выдвигать токен, .+ сопоставляя еще один символ, а затем снова оценивая оставшееся регулярное выражение.
. +? в конечном итоге потребует: srfsf.jwbefw, прежде чем сопоставить точку, а затем сопоставит com.ua.

Но реализация ? также создает проблемы.

Добавление в вопросительный знак делает это сначала + ленивым, но затем заставляет group1 соответствовать bb.prontube.ru вместо prontube.ru

Это связано с тем, что первый период после совпадения bb, а затем внутри группы 1 (.*?) будет совпадать с bb.prontube. до совпадения \.(ru|ua|com\.ua|com|net|info))$ с .ru

Чтобы избежать этого, измените эту третью группу с (.*?) на ([\w-]*?), чтобы она не содержала . только буквы и цифры или тире.

Полученное регулярное выражение:
.+?\.(([\w-])*?\.(ru|ua|com\.ua|com|net|info))$

Обратите внимание, что вам не нужно захватывать какие-либо группы, кроме первой. Добавление?: Делает варианты ДВУ без записи.

последнее изменение:
.+?\.([\w-]*?\.(?:ru|ua|com\.ua|com|net|info))$