Спецификации в вопросе не очень понятны, поэтому я просто предположу, что строка может содержать только буквы и цифры ASCII, с дефисами, подчеркиванием и пробелами в качестве внутренних разделителей. Основная проблема заключается в том, что первый и последний символы не являются разделителями и что в строке никогда не бывает более одного разделителя (эта часть в любом случае кажется ясной). Вот самый простой способ:
/^[A-Za-z0-9]+(?:[ _-][A-Za-z0-9]+)*$/
После сопоставления одного или нескольких буквенно-цифровых символов, , если есть разделитель, за ним должен следовать один или несколько буквенно-цифровых символов; при необходимости повторите.
Давайте посмотрим на регулярные выражения из некоторых других ответов.
/^[[:alnum:]]+(?:[-_ ]?[[:alnum:]]+)*$/
По сути, это то же самое (при условии, что ваш regex-вариант поддерживает нотацию класса символов POSIX), но зачем делать разделитель необязательным? Во-первых, единственная причина, по которой вы оказались бы в этой части регулярного выражения, это наличие разделителя или другого недопустимого символа.
/^[a-zA-Z0-9]+([_\s\-]?[a-zA-Z0-9])*$/
С другой стороны, это работает только , поскольку разделитель является необязательным. После первого разделителя он может соответствовать только одному буквенно-цифровому символу за раз. Чтобы соответствовать больше, он должен повторять всю группу: нулевые разделители, за которыми следуют один алфавитно-цифровой, снова и снова. Если за вторым [a-zA-Z0-9]
следовал знак плюс, он мог бы найти совпадение по гораздо более прямому маршруту.
/^[a-zA-Z0-9][a-zA-Z0-9_\s\-]*[a-zA-Z0-9](?<![_\s\-]{2,}.*)$/
При этом используется неограниченный вид сзади, что является очень редкой функцией, но вы можете использовать прогноз с тем же эффектом:
/^(?!.*[_\s-]{2,})[a-zA-Z0-9][a-zA-Z0-9_\s\-]*[a-zA-Z0-9]$/
Это выполняет, по сути, отдельный поиск двух последовательных разделителей и не дает совпадения, если находит один. В этом случае основной корпус должен только убедиться, что все символы являются буквенно-цифровыми или разделителями, причем первый и последний из них являются буквенно-цифровыми. Поскольку эти два поля обязательны, имя должно содержать не менее двух символов.
/^[a-zA-Z0-9]+([a-zA-Z0-9](_|-| )[a-zA-Z0-9])*[a-zA-Z0-9]+$/
Это ваше собственное регулярное выражение, и оно требует, чтобы строка начиналась и заканчивалась двумя буквенно-цифровыми символами, и если в строке есть два разделителя, между ними должно быть ровно два алфавитно-цифровых символа. Так что ab
, ab-cd
и ab-cd-ef
будут совпадать, а a
, a-b
и a-b-c
не будут.
Кроме того, как указали некоторые комментаторы, (_|-| )
в вашем регулярном выражении должно быть [-_ ]
. Эта часть не является неправильной , но если у вас есть выбор между чередованием и классом символов, вы всегда должны использовать класс символов: они более эффективны, а также более читабельны.
Опять же, меня не беспокоит вопрос о том, должны ли "буквенно-цифровые" включать не-ASCII-символы или точное значение "пробела", как применять политику несмежных внутренних разделителей с регулярным выражением.