Могу ли я улучшить эту проверку регулярных выражений для действительных доменных имен? - PullRequest
6 голосов
/ 30 декабря 2008

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

Ответы [ 6 ]

28 голосов
/ 30 декабря 2008

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

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

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

4 голосов
/ 31 декабря 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')

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

0 голосов
/ 30 декабря 2008

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

0 голосов
/ 30 декабря 2008

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

0 голосов
/ 30 декабря 2008

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

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

0 голосов
/ 30 декабря 2008

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

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

...