Групповой захват группы 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
?
Ответы
Ответ 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))$