Проблема с вашим регулярным выражением заключается в том, как оно обрабатывает символы в строке, представляющей доменное имя.
Исходное регулярное выражение:
```php
$reg = '#[a-z0-9]+[_-]?[a-z0-9]+\.[a-z]{2,}#';
```
Давайте разберемся по частям:
1. **[a-z0-9]+** — это соответствует одной или более буквам и цифрам.
2. **[_-]?** — это соответствует нулю или одному символу подчеркивания или тире.
3. **[a-z0-9]+** — снова соответствует одной или более буквам и цифрам.
4. **\.** — соответствует точке, которая разделяет имя домена и его расширение.
5. **[a-z]{2,}** — соответствует двум или более буквам, что правильно для доменной зоны.
С regex `#\.[a-z]{2,}#` доменное имя будет проверяться только на наличие точек в конце, и не будет проверяться все символы, если они соответствуют обычным правилам.
Проблема со строкой `si$te.com` заключается в следующем:
- В вашем регулярном выражении не учтено, что часть перед точкой (называемая "имя домена") может содержать только буквы и цифры, а не знаки, такие как `$`.
- Ваше регулярное выражение в текущем виде допускает теоретически любую букву, цифры и любой символ `_` или `-` именно в связи "[a-z0-9]+[_-]?[a-z0-9]+".
Теперь, давайте рассмотрим, что будет, если мы уберем тире и нижнее подчеркивание:
```php
$reg = '#[a-z0-9]+\.[a-z]{2,}#';
```
С этим выражением вы проверяете, что:
1. Имя домена начинается с хотя бы одной буквы или цифры.
2. После этого должно быть `.`, за которым следует от двух до бесконечности букв.
Данное выражение не проверяет символы до точки. Оно проверяет наличие любого подходящего домена с нужной доменной зоной.
Поэтому в результате `preg_match` вернет `1` для `si$te.com`, так как находит соответствие для `.com`, а часть перед точкой не проверяется на допустимость.
### Исправленный Регулярное выражение
Чтобы корректно проверять доменные имена, учитывая только допустимые символы, можно использовать следующее регулярное выражение:
```php
$reg = '#^(?!.*[^a-z0-9._-])[a-z0-9]+([.-][a-z0-9]+)*\.[a-z]{2,}$#';
```
- `^(?!.*[^a-z0-9._-])` — отрицательная проверка, которая гарантирует, что в строке нет недопустимых символов.
- `[a-z0-9]+` — начальная часть доменного имени.
- `([.-][a-z0-9]+)*` — допускает подчеркивание и тире как разделители между элементами доменного имени.
- `\.[a-z]{2,}$` — проверка, что за именем домена идет точка, а затем от двух до бесконечности букв.
Это регулярное выражение будет правильно проверять только существующие доменные имена.