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

Это похоже на правила, которые я определил, но я только начинаю изучать регулярное выражение сегодня, поэтому мне интересно, правильно ли оно.

Правила:

  • Имена пользователей могут состоять из нижнего регистра и столицы
  • Имена пользователей могут состоять из буквенно-цифровых символы
  • Имена пользователей могут состоять из подчеркивания и дефисы и пространства
  • Не может быть двух символов подчеркивания, двух подстроек или два пробела подряд
  • Не может быть подчеркивания, hypen или пространство в начале или конце

Шаблон регулярного выражения:

/^[a-zA-Z0-9]+([a-zA-Z0-9](_|-| )[a-zA-Z0-9])*[a-zA-Z0-9]+$/

Ответ 1

Спецификации в вопросе не очень ясны, поэтому я просто предполагаю, что строка может содержать только буквы и цифры ASCII с дефисами, подчеркиваниями и пробелами в качестве внутренних разделителей. Мясо проблемы заключается в том, что первый и последний символы не являются разделителями и что не более одного разделителя подряд (эта часть кажется ясной, во всяком случае). Вот простейший способ:

/^[A-Za-z0-9]+(?:[ _-][A-Za-z0-9]+)*$/

После сопоставления одного или нескольких буквенно-цифровых символов, если есть разделитель, за ним следует одна или несколько буквенно-цифровых символов; повторите по мере необходимости.

Посмотрите на регулярные выражения из некоторых других ответов.

/^[[:alnum:]]+(?:[-_ ]?[[:alnum:]]+)*$/

Это фактически то же самое (если ваш аромат регулярного выражения поддерживает нотацию символьного класса 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,}.*)$/

Это использует неограниченный lookbehind, который является очень редкой функцией, но вы можете использовать lookahead для того же эффекта:

/^(?!.*[_\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-символы или точный смысл "пространства", просто как обеспечить соблюдение политики несмежных внутренних разделителей с регулярным выражением.

Ответ 2

Вы можете упростить регулярное выражение:

/^[a-zA-Z0-9]+([_ -]?[a-zA-Z0-9])*$/

Визуализировано с помощью Regexper:

Визуализация регулярного выражения проверки имени пользователя.

Как вы можете видеть, имя пользователя всегда должно начинаться с буквенно-цифрового символа. Специальные символы (_, , -) должны сопровождаться буквенно-цифровым символом. Последний символ должен быть буквенно-цифровым символом.

Ответ 3

 ([a-zA-Z0-9](_|-| )[a-zA-Z0-9])*

- 0 или более повторений букв, dashspace, alphanum.

Таким образом, он будет соответствовать

a_aa_aa_a

но не

aaaaa

Полное regexp не может соответствовать

a_aaaaaaaaa_a for example.

Оглянитесь на то, что вы хотите:

* Usernames can consist of lowercase and capitals or alphanumerica characters
* Usernames can consist of alphanumeric characters
* Usernames can consist of underscore and hyphens and spaces
* Cannot be two underscores, two hypens or two spaces in a row
* Cannot have a underscore, hypen or space at the start or end

Начало простое... просто совпадение с буквенным алфавитом, затем (включение двух в правиле строки) a (alphanum или dashspace) * и снова и снова в алфавите.

Чтобы избежать двух помех в строке, вам, вероятно, нужно понять lookahead/lookbehind.

О, и в отношении другого ответа: Пожалуйста, загрузите Espresso, он ДЕЙСТВИТЕЛЬНО поможет вам разобраться в этом.

Ответ 4

Я предлагаю написать некоторые модульные тесты, чтобы поместить Regex через него. Это также поможет через несколько месяцев, когда вы обнаружите проблему с Regex и должны ее обновить.

Ответ 5

  • Alphanumerical - это не только [a-zA-Z0-9], он акцентирован, кириллица, греческий и другие буквы, которые могут использоваться в имени пользователя.

  • (_|-| ) может быть заменен на [-_ ] класс символов

Ответ 6

Использование класса символов POSIX для буквенно-цифровых символов, чтобы заставить его работать с акцентированными и другими иностранными алфавитными символами:

/^[[:alnum:]]+([-_ ]?[[:alnum:]])*$/

Более эффективный (предотвращает захват):

/^[[:alnum:]]+(?:[-_ ]?[[:alnum:]]+)*$/

Они также предотвращают последовательность из более чем одного пробела/дефиса/подчеркивания в комбинации. Из вашей спецификации не следует, желательно ли это, но ваше собственное регулярное выражение кажется, что это то, что вы хотите.

Ответ 7

Еще одна рекомендация для Expresso 3.0 - очень проста в использовании и создавать строки с.

Ответ 8

Ваше регулярное выражение не работает. Жесткая часть - это проверка последовательных пробелов/дефисов. Вы можете использовать этот, который использует look-behind:

/^[a-zA-Z0-9][a-zA-Z0-9_\s\-]*[a-zA-Z0-9](?<![_\s\-]{2,}.*)$/

Ответ 9

По внешнему виду это правило не будет соответствовать чему-то вроде "a_bc", "ab_c", "a_b" или "a_b_c".

Попробуйте: /^[a-zA-Z0-9]+([_\s\-]?[a-zA-Z0-9])*$/ который соответствует указанным выше случаям, но не представляет собой комбинацию пробелов, тире или подчеркивания рядом друг с другом. Например: "_-" или "_" не разрешены.

Ответ 10

По моему мнению, было бы лучше добавить ограниченную область применения к этой модели.

[a-zA-Z0-9] + ([_ -]? [a-zA-Z0-9]) {5,40} $

enter image description here