Могу ли я улучшить эту проверку регулярного выражения для действительных доменных имен?

Итак, я работал над этим регулярным выражением доменного имени. Пока что, похоже, появляются доменные имена с SLD и TLD (с дополнительным ccTLD), но есть дублирование списка TLD. Можно ли еще реорганизовать это?

params[:domain_name].downcase.strip.match(/^[a-z0-9\-]{2,63}
\.((a[cdefgilmnoqrstuwxz]|aero|arpa)|(b[abdefghijmnorstvwyz]|biz)|
(c[acdfghiklmnorsuvxyz]|cat|com|coop)|d[ejkmoz]|(e[ceghrstu]|edu)|f[ijkmor]|
(g[abdefghilmnpqrstuwy]|gov)|h[kmnrtu]|(i[delmnoqrst]|info|int)|
(j[emop]|jobs)|k[eghimnprwyz]|l[abcikrstuvy]|
(m[acdghklmnopqrstuvwxyz]|me|mil|mobi|museum)|(n[acefgilopruz]|name|net)|(om|org)|
(p[aefghklmnrstwy]|pro)|qa|r[eouw]|s[abcdeghijklmnortvyz]|
(t[cdfghjklmnoprtvwz]|travel)|u[agkmsyz]|v[aceginu]|w[fs]|y[etu]|z[amw])
(\.((a[cdefgilmnoqrstuwxz]|aero|arpa)|(b[abdefghijmnorstvwyz]|biz)|
(c[acdfghiklmnorsuvxyz]|cat|com|coop)|d[ejkmoz]|(e[ceghrstu]|edu)|f[ijkmor]|
(g[abdefghilmnpqrstuwy]|gov)|h[kmnrtu]|(i[delmnoqrst]|info|int)|
(j[emop]|jobs)|k[eghimnprwyz]|l[abcikrstuvy]|
m[acdghklmnopqrstuvwxyz]|mil|mobi|museum)|
(n[acefgilopruz]|name|net)|(om|org)|
(p[aefghklmnrstwy]|pro)|qa|r[eouw]|s[abcdeghijklmnortvyz]|
(t[cdfghjklmnoprtvwz]|travel)|u[agkmsyz]|v[aceginu]|w[fs]|y[etu]|z[amw]))?$/)

person Josh Delsman    schedule 30.12.2008    source источник
comment
Каков ваш вариант использования такого регулярного выражения, которое необходимо поддерживать при создании новых доменов?   -  person mark    schedule 30.12.2008
comment
Поскольку все ответы, похоже, дают другие способы поиска TLD, я предлагаю переименовать этот вопрос, чтобы избежать дублирования в будущем (если люди действительно не начнут отвечать на вопрос о рефакторинге)   -  person TheSoftwareJedi    schedule 31.12.2008
comment
хорошая идея - это действительно не проблема с регулярным выражением.   -  person Alnitak    schedule 31.12.2008
comment
Ужасно плохая идея, особенно зашитый список TLD.   -  person bortzmeyer    schedule 05.01.2009


Ответы (6)


Пожалуйста, пожалуйста, пожалуйста, не используйте фиксированное и ужасно сложное регулярное выражение, подобное этому, для сопоставления с известными доменными именами.

Список TLD не статичен, особенно с учетом того, что ICANN ищет оптимизированный процесс для новых gTLD. Иногда меняется даже список ccTLD!

Взгляните на список, доступный на http://publicsuffix.org/, и напишите код, который можно загрузить и проанализировать этот список вместо этого.

person Alnitak    schedule 30.12.2008

Загрузите это: http://data.iana.org/TLD/tlds-alpha-by-domain.txt

Пример использования (на Python):

import re
def validate(domain):
    valid_domains = [ line.upper().replace('.', '\.').strip() 
                      for line in open('domains.txt') 
                      if line[0] != '#' ]
    r = re.compile(r'^[A-Z0-9\-]{2,63}\.(%s)$' % ('|'.join(valid_domains),))
    return True if r.match(domain.upper()) else False


print validate('stackoverflow.com')
print validate('omnom.nom')

Вы можете исключить построение списка доменов из функции проверки, чтобы повысить производительность.

person Steve Losh    schedule 30.12.2008
comment
Результаты не такие, как ожидалось для таких доменов, как awesomedomain.co.uk - TLD не считается .uk, это .co.uk. Лучше использовать что-то вроде publicsuffix.org - person Dan Esparza; 12.05.2009
comment
@DanEsparza: И все же publicsuffix.org записывает его как * .uk и не как co.uk. - person Dennis Williamson; 12.11.2011
comment
@DennisWilliamson * в записи для *.uk означает, что каждый субдомен .uk является общедоступным , за исключением явно указанных. - person Alnitak; 29.10.2012

Возможно, я недостаточно знаю о доменных именах. Но почему совпадают такие домены, как "foo.info.com"? Похоже, что в данном случае доменное имя - «info.com».

И вы можете убедиться, что имя начинается с [a-z \ d]. Не думаю, что можно зарегистрировать домен, который начинается с тире?

person PEZ    schedule 30.12.2008
comment
Не все доменные имена состоят из двух частей. Единственный пример: ck - это домен островов Кука (попробуйте ck или ck); мой собственный домен состоит из трех частей (nichesoftware.co.nz) из-за структуры внутри TLD .nz. - person Bevan; 31.12.2008

Как вы уже написали, часть TLD эквивалентна, но длиннее (\.<tldpart>){1,2}, но я уверен, что ее можно исправить для дублирования ...

edit: yech, нет, это было бы возможно, но, по сути, очень медленный список грубой силы для обработки дубликатов, я думаю. Проще и быстрее поместить возможные пары стран TLD и SLD + в большую хэш-карту и проверить на соответствие подстроку.

person annakata    schedule 30.12.2008

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

person sammich    schedule 30.12.2008
comment
RFC технически не разрешает полностью числовые части домена, но на практике регистраторы и серверы имен разрешают их уже много лет. - person nobody; 31.12.2008

Вы можете создать регулярное выражение как строку, а затем выполнить Regexp.new (строка).

person Jules    schedule 30.12.2008