@BjornBorn

Как правильно составить регулярное выражение для проверки доменного имени?

Нужно определить, является ли переданная строка доменом.
Массив строк:
$arr[] = 'site.ru';
$arr[] = 'site.com';
$arr[] = 'my-site.com';
$arr[] = 'my-cool-site.com';
$arr[] = 'my_site.com';
$arr[] = 'site123.com';
$arr[] = 'site.travel';
$arr[] = 'si$te.com';
$arr[] = 'site.r';


$reg   = '#[a-z0-9]+[_-]?[a-z0-9]+\.[a-z]{2,}#';
foreach ($arr as $str) {
    echo $str . ' - ' . preg_match($reg, $str) . '<br>';
}

В результате получается:
site.ru - 1
site.com - 1
my-site.com - 1
my-cool-site.com - 1
my_site.com - 1
site123.com - 1
site.travel - 1
si$te.com - 1
site.r - 0

Почему строка
$arr[] = 'si$te.com';
определяется как доменное имя?
И почему если в регулярном выражении удалить тире и нижнее подчеркивание, то всё будет работать точно так же?
$reg = '#[a-z0-9]+\.[a-z]{2,}#';
  • Вопрос задан
  • 411 просмотров
Пригласить эксперта
Ответы на вопрос 5
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
Почему строка $arr[] = 'si$te.com'; определяется как доменное имя?

Потому что te.com определяется как доменное имя, а условие, что попадать под маску должна полная строка у вас не наложено. Ну и, на самом деле, национальные домены первого уровня в punycode могут содержать цифры.
- $reg   = '#[a-z0-9]+[_-]?[a-z0-9]+\.[a-z]{2,}#';
+ $reg   = '#^(?:[a-z0-9][a-z0-9-_]*\.)+(?:[a-z]{2,}|xn--[a-z0-9]{4,})$#i';
Ответ написан
delphinpro
@delphinpro Куратор тега PHP
frontend developer
$arr = [
    'site.ru',
    'site.com',
    'my-site.com',
    'my-cool-site.com',
    'my_site.com',
    'site123.com',
    'site.travel',
    'si$te.com',
    'site.r',
];
foreach ($arr as $str) {
    $result = filter_var($str, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME);
    echo $str . ' - ' . ($result === false ? 'INVALID' : $result) . '<br>';
}

// site.ru - site.ru
// site.com - site.com
// my-site.com - my-site.com
// my-cool-site.com - my-cool-site.com
// my_site.com - INVALID
// site123.com - site123.com
// site.travel - site.travel
// si$te.com - INVALID
// site.r - site.r
Ответ написан
Комментировать
402d
@402d
начинал с бейсика на УКНЦ в 1988
имхо бесполезная работа. Потому что
не уточнено что считать доменом.
Регуляркой Вы можете проверить только соответствует ли строка RFC 1035.
Но и то Вы скорее всего будете проверять двух уровненые домены.
ок. последний (верхний уровень) - может стоит проверять значение на существование такой доменной зоны ?
com - есть, условно c9m - пока никто на себя не зарегил.
И тут у нас уже пара тысяч зон есть. В регулярке все не перечислить.
далее проверим второй уровень. в зоне ру 2-63 символа.
Ок ну убедились, что допустимо. Но имя может быть запрещено
Н-р: POLOVOI_ORGAN(из 3 или 5 букв).RU и все проверки покажут, что имя свободное, а вот при регистрации получишь отлуп. Имя зарегено - но может быть НЕДЕЛЕГИРОВАНО / ПРИПАРКОВОНО / РЕАЛЬНО ИСПОЛЬЗУЕТСЯ (сайт и/или почта)

Третий уровень *.msk.ru - доменная зона.

Так, что фиг вы регуляркой проверите, что строка это ДОМЕН.
Ответ написан
Комментировать
saboteur_kiev
@saboteur_kiev
software engineer
^((?!-)[A-Za-z0-9-]{1, 63}(?<!-)\\.)+[A-Za-z]{2, 6}$

Но это не проверка на доменное имя, а проверка что данная строка похожа на доменное имя.

Можно выполнить проверку на регулярку а потом просто выполнить резолв домена через какой-нить nslookup
Ответ написан
Комментировать
Sanes
@Sanes
Не всё так просто с доменами. Регуляркой не обойтись. Пользуйтесь библиотеками. Для php раз, два
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы