Вопрос:
Кто-нибудь знает, как написать регулярное выражение, которое позволяет только a-zA-Z0-9.- (буквы, цифры, точки и тире) НО, которые никогда не начинаются или не заканчиваются точкой или тире?
Я попробовал следующее:
/^[^.-][a-zA-Z0-9.-]+[^.-]$/
… но если я пишу что-то вроде “john @”, он работает, и я не хочу, потому что @не разрешено.
Ответ №1
Subdomain
В соответствии с актуальными рекомендациями в Интернете (RFC3986 раздел 2.2, который, в свою очередь, ссылается на: RFC1034 раздел 3.5 и RFC1123 раздел 2.1), субдомен (который является частью имени хоста DNS-домена), должны соответствовать нескольким требованиям:
- Каждая часть поддомена должна иметь длину не более 63.
- Каждая часть субдомена должна начинаться и заканчиваться буквенно-цифровым (например, буквы [A-Za-z] или цифры [0-9]).
- Каждая часть субдомена может содержать дефисы (дефисы), но не может начинаться или заканчиваться дефисом.
Вот фрагмент выражения для части субдомена, которая отвечает этим требованиям:
[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?
Обратите внимание, что этот фрагмент выражения не должен использоваться отдельно – для этого требуется включение граничных условий в большем контексте, как показано в следующем выражении для имени хоста DNS…
Имя хоста DNS
Именованный узел (не IP-адрес) должен отвечать дополнительным требованиям:
- Имя хоста может состоять из нескольких частей субдомена, каждый из которых разделен одной точкой.
- Длина общего имени хоста не должна превышать 255 символов.
- Домен верхнего уровня (самая правая часть имени хоста DNS) должен быть одним из международно признанных значений. Список допустимых доменов верхнего уровня поддерживается IANA.ORG. (См. Текущий список голых костей здесь: http://data.iana.org/TLD/tlds-alpha-by-domain.txt).
С этим умом, здесь прокомментированное регулярное выражение (в синтаксисе PHP), которое будет псевдоопределять имя хоста DNS: (Обратите внимание, что это включает модифицированную версию вышеуказанного выражения для субдомена и добавляет к нему комментарии).
Обновление 2016-08-20:. Поскольку этот ответ был первоначально опубликован еще в 2011 году, количество доменов верхнего уровня взорвалось. По состоянию на август 2016 года в настоящее время более 1400. Оригинальное регулярное выражение для этого ответа включало в себя все эти, но это не логин. В новом регулярном выражении ниже используется другое выражение для домена верхнего уровня. Алгоритм исходит из: Спецификация имени доменного имени верхнего уровня-liman-tld-names-06.
$DNS_named_host = ‘%(?#!php/i DNS_named_host Rev:20160820_0800) # Match DNS named host domain having one or more subdomains. # See: http://stackoverflow.com/a/7933253/433790 ^ # Anchor to start of string. (?!.{256}) # Whole domain must be 255 or less. (?: # One or more sub-domains. [a-z0-9] # Subdomain begins with alpha-num. (?: # Optionally more than one char. [a-z0-9-]{0,61} # Middle part may have dashes. [a-z0-9] # Starts and ends with alpha-num. )? # Subdomain length from 1 to 63. . # Required dot separates subdomains. )+ # End one or more sub-domains. (?: # Top level domain (length from 1 to 63). [a-z]{1,63} # Either traditional-tld-label = 1*63(ALPHA). | xn--[a-z0-9]{1,59} # Or an idn-label = Restricted-A-Label. ) # End top level domain. $ # Anchor to end of string. %xi’; // End $DNS_named_host.
Обратите внимание, что это выражение не является совершенным. Он требует одного или нескольких поддоменов, но технически хост может состоять из TLD, не имеющего субдомена (но это редко).
Обновление 2014-08-12: Добавлено упрощенное выражение для поддомена, которое не требует чередования.
Обновление 2016-08-20: Измененное регулярное выражение имени хоста DNS (в общем) соответствует новому большому количеству допустимых доменов верхнего уровня. Кроме того, вырезали из ответа лишний материал.
Ответ №2
Вы хотите, чтобы первый и последний символы были ограничены буквенно-цифровыми. То, что у вас есть, позволяет первыми и последними символами быть чем угодно, кроме точки и тире. Это соответствует описанию:
/^[a-zA-Z0-9][a-zA-Z0-9.-]+[a-zA-Z0-9]$/ Ответ №3
В нашем проекте мы сопоставляем субдомены, подобные этому
Клиент JS
^([A-Za-z0-9](?:(?:[-A-Za-z0-9]){0,61}[A-Za-z0-9])?(?:.[A-Za-z0-9](?:(?:[-A-Za-z0-9]){0,61}[A-Za-z0-9])?){2,})$
Серверный Ruby
A([A-Za-z0-9](?:(?:[-A-Za-z0-9]){0,61}[A-Za-z0-9])?(?:.[A-Za-z0-9](?:(?:[-A-Za-z0-9]){0,61}[A-Za-z0-9])?){2,})z Ответ №4
Попробуйте следующее:
/^[a-zA-Z0-9][a-zA-Z0-9.-]*[a-zA-Z0-9]$/
НО длина строки должна быть не менее 2 символов для соответствия: a-zA-Z0-9 и a-zA-Z0-9. Чтобы этого избежать, вы можете использовать это регулярное выражение:
/^[a-zA-Z0-9][a-zA-Z0-9.-]*$/
Но вам нужно сделать дополнительную проверку, чтобы убедиться, что конец строки не является ни точкой, ни тире.
Ответ №5
Вот решение DOMAIN + SUBDOMAIN, которое может помочь кому-то еще:
/^([a-zA-Z0-9]([-a-zA-Z0-9]{0,61}[a-zA-Z0-9])?.)?([a-zA-Z0-9]{1,2}([-a-zA-Z0-9]{0,252}[a-zA-Z0-9])?).([a-zA-Z]{2,63})$/
который проходит следующие тесты Chai:
const expect = require(‘chai’).expect; function testDomainValidNamesRegExp(val) { let names = /^([a-zA-Z0-9]([-a-zA-Z0-9]{0,61}[a-zA-Z0-9])?.)?([a-zA-Z0-9]([-a-zA-Z0-9]{0,252}[a-zA-Z0-9])?).([a-zA-Z]{2,63})$/; return names.test(val); } let validDomainNames = [ «example.com», «try.direct», «my-example.com», «subdomain.example.com», «example.com», «example23.com», «regexp-1222.org», «read-book.net», «org.host.org», «org.host.org», «velmart.shop-products.md», «ip2email.terronosp-222.lb», «stack.com», «sta-ck.com», «sta—ck.com», «9sta—ck.com», «sta—ck9.com», «stack99.com», «99stack.com», «sta99ck.com», «sub.do.com», «ss.sss-ss.ss», «s.sss-ss.ss», «s.s-s.ss», «test.t.te» ]; let invalidDomainNames = [ «example2.com222», «@example.ru:?», «example22:89», «@jefe@dd.ru@22-«, «example.net?1222», «example.com:8080:», «.example.com:8080:», «—test.com», «$dollars$.gb», «sell-.me», «open22.the-door@koll.ru», «mem-.wer().or%:222», «pop().addjocker.lon», «regular-l=.heroes?», » ecmas cript-8.org «, «example.com::%», «example:8080», «example», «examaple.com:*», «-test.test.com», «-test.com», «dd-.test.com», «dfgdfg.dfgdf33.e», «dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd-.test.com», «dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd.testttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt.com», «d-.test.com» ]; describe(«Test Domain Valid Names RegExp», () => { validDomainNames.forEach((val) => { it(‘Text: ${val}’, () => { expect(testDomainValidNamesRegExp(val)).to.be.true; }); }); }); describe(«Test Domain Invalid Names RegExp», () => { invalidDomainNames.forEach((val) => { it(‘Text: ${val}’, () => { expect(testDomainValidNamesRegExp(val)).to.be.false; }); }); });
Другие тесты очень приветствуются!
Ответ №6
Попробуйте этот параметр reg-exp /^[a-zA-Z0-9][a-zA-Z0-9.-]*[a-zA-Z0-9]$/
Проблема с вашим кодом была [^.-] в начале и в конце совпадала с любым символом excpet ‘.’ или ‘-‘, который соответствует всем символам, а не обязательно [a-zA-Z0-9]
Ответ №7
Попробуйте regex:
^(?![-.])[a-zA-Z0-9.-]+(?<![-.])$ Ответ №8
Вот регулярное выражение для субдомена, который
- Разрешить точку (.), Подчеркивание (_), тире (-) в строке
- Не разрешать точку (.), Подчеркивание (_), тире (-) в первом и последнем символе
-
Разрешить буквенно-цифровой в строке
^[a-zA-Z0-9]+[a-zA-Z0-9-._]*[a-zA-Z0-9]+$
Правильный пример
- abc.com
- abc_xyz.com
- abc.xyz.com
- азбука
Неверный пример
- а.
- -abc
- abc-
- хуг. abc-