Здравствуйте.
Стоит задача 1 регуляркой захватывать все поддомены в *.google.com, кроме случаев, когда домен 3 уровеня play или gemini.
Т.е. вот такие варианты, должны исключаться
play.google.com
test.play.google.com
sub.test.play.google.com
аналогично и с gemini.
Составил такую регулярку, через негативную ретроспективную проверку: (([a-z0-9\-]+\.)*(?<!(play|gemini)\.))?google\.com
Составил тестовый список строк с урлами:
google.com
www.google.com play.google.com
test.play.google.com
play1.google.com
test.play1.google.com 1play.google.com
test.1play.google.com
1play1.google.com
test.1play1.google.com
te-st.api.google.com
Но по данным regexr.com выделенные жирным строки не попали в регулярку.
3 и 4 строка верно исключились, отлично.
Не могу понять почему, если перед play имеет подстрока, то она исключается. Ведь 1play.google.com это уже другой ваирант.
Подскажите пожалуйста как исправить?
Спасибо.
AUser0, можно и так. Но автор не указал, где будет использоваться регулярка. Если это для кода на JS, то в Сафари поддержка lookbehind появилась совсем недавно, и на версии до 16.4 будет большой "превед"
Александр, подскажите пожалуйста, а как работает данная регулярка, в том плане, что если мы заглядываем справа (?!, то наша ретроспективная проверка получается относится к блоку ([a-z0-9_-]+\.)*
Но тогда получается, что после найденных поддоменов 4 и более уровня будет идти ещё поддомен 3 уровня, который вы указываете через [a-z0-9_-]+\. который идёт перед google\.com.
На первых взгляд кажется, что регулярка исключит вот такие строки
play.sub3.google.com
test.play.sub3.google.com
проверка (?!(play|gemini)\.) относится к куску справа от неё, т.е. как раз к третьему уровню. Она потому и называется lookahead, т.е. "заглядывание вперед". Причем она делается сразу либо от начала строки, либо от точки (т.е. с того места, где она в регулярке), и как следствие не сработает на поддомене, к примеру, 1play или 2gemini (т.е. на поддоменах, оканчивающихся на эти слова, но ими не являющихся)
/Ludovic(?!XVI)/
LudovicXV, LudovicXVI, LudovicXVIII, LudovicLXVII, LudovicXXL
Кроме просмотра вперед, существует просмотр назад или ретроспективный поиск. Он работает похожим образом, но ищет совпадения символов, расположенных после сгруппированной в скобках части регулярного выражения, которая не будет включена в сопоставление.
Как видно из обоих описний, проверка (?! указывается справа от проверяемого выражения (подстроки).
А слева от проверяемого выражения указывается (?<! конструкция:
Негативная ретроспективная проверка: (?<!Y)X, ищет совпадение с X при условии, что перед ним НЕТ Y
Константин, поясню на более общем примере: вот регулярка A(?!B)C , где буквы - тоже какие-то регулярки. Она ищет совпадение, в котором первая часть соответствует регулярке A, а вторая - регулярке C, но в то же время вторая часть не должна соответствовать регулярке B. То есть B и C смотрят на один и тот же кусок текста.
Пример: найти цифру, за которой идет любая буква, кроме F:
\d(?!F)[A-Za-z]
(?!F) как бы наслаивается на то, что справа от него. Иными словами, lookahead необязательно ставить в конец регулярки, можно в середину/начало