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

Итак, я работал над этим регулярным выражением имени домена. До сих пор он, кажется, забирал доменные имена с 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]))?$/)

Ответы

Ответ 1

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

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

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

Ответ 2

Скачайте это: 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')

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

Ответ 3

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

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

Ответ 4

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

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

Ответ 5

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

Ответ 6

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