Могу ли я улучшить эту проверку регулярных выражений на наличие действительных доменных имен?
Вопрос
Итак, я работал над этим регулярным выражением доменного имени.Пока, похоже, он подбирает доменные имена с 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(строка).