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

StackOverflow https://stackoverflow.com/questions/399932

  •  29-08-2019
  •  | 
  •  

Вопрос

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

Решение

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

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

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

Другие советы

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top