#ruby-on-rails #regex
#ruby-on-rails #регулярное выражение
Вопрос:
Я пытаюсь написать проверку имени пользователя, которая имеет следующие ограничения:
- Должно содержать как минимум 1 букву (a-zA-Z)
- Может содержать только цифры, буквы или подчеркивания
Допустимы следующие примеры: abc123, my_name, 12345a
Следующие примеры недопустимы: 123456, my_name!, _1235
Я нашел кое-что об использовании положительных предвидений для ограничения буквы: (?=.*[a-zA-Z]), и похоже, что для второго ограничения может быть какой-то отрицательный предвидение, но я не уверен, как объединить их в одно регулярное выражение. (Примечание… Я не совсем понимаю, что делает часть .* внутри предварительного просмотра …)
Это что-то вроде этого: /(?=.*[a-zA-Z])(?!.*[^a-zA-Z0-9_])/
Редактировать:
Поскольку в вопросе запрашивается регулярное выражение, ответ, который я принимаю, таков:
/^[a-zA-Z0-9_]*[a-zA-Z][a-zA-Z0-9_]*$/
Однако то, что я на самом деле собираюсь реализовать, — это предложение Брайана Оукли разделить его на несколько проверок меньшего размера. Это упрощает чтение и расширение в будущем в случае изменения требований. Спасибо всем!
И поскольку я пометил это ruby-on-rails, я включу код, который я на самом деле использую:
validate :username_format
def username_format
has_one_letter = username =~ /[a-zA-Z]/
all_valid_characters = username =~ /^[a-zA-Z0-9_] $/
errors.add(:username, "must have at least one letter and contain only letters, digits, or underscores") unless (has_one_letter and all_valid_characters)
end
Ответ №1:
/^[a-zA-Z0-9_]*[a-zA-Z][a-zA-Z0-9_]*$/
: за 0 или более допустимыми символами следует один алфавитный, за которым следует 0 или более допустимых символов, которые должны быть как началом, так и концом строки.
Комментарии:
1. Мило, в первом тесте отсутствует _ для 0 или более допустимых значений, но в остальном это работает!
Ответ №2:
Легко проверить, содержит ли шаблон какие-либо недопустимые символы, и легко проверить, есть ли хотя бы одна буква. Попытка сделать все это в одном регулярном выражении затруднит понимание вашего кода.
Я рекомендую провести два теста. Поместите тесты в функции, чтобы сделать ваш код абсолютно мертвым — простым для понимания:
if no_illegal_characters(string) amp;amp; contains_one_alpha(string) {
...
}
Для первого вы можете использовать шаблон ^[a-zA-Z0-9_] $
, а для второго вы можете использовать [a-zA-Z]
.
Если вам не нравятся дополнительные функции, это нормально, просто не пытайтесь решить проблему с помощью одного сложного для чтения регулярного выражения. За втискивание как можно большего количества функций в одно выражение бонусные баллы не начисляются.
Комментарии:
1. В твоем регулярном выражении «no_illegal_characters()» обнаружена небольшая ошибка, Брайан. На данный момент регулярное выражение гласит: «длина строки должна составлять всего 1 символ от начала до конца». Вместо
^[a-zA-Z0-9_]$
этого должно быть^[a-zA-Z0-9_] $
.2. Спасибо @wyatt, я изменил выражение, включив
Ответ №3:
самое простое регулярное выражение, которое решает вашу проблему, это:
/^[a-zA-Z0-9][a-zA-Z0-9_]*$/
Я рекомендую вам попробовать это вживую наhttp://rubular.com /
Комментарии:
1. Это не идеальное решение: оно не допускает 12345a.
2. Похоже, что это очень близко, но также наложено ограничение, что оно должно начинаться с буквы, поэтому 12345a не проходит.
3. Извините, я думал, что 12345a неверен: правильный /^[a-zA-Z0-9][a-zA-Z0-9_] *$/
4. @Ireneusz Skrobis: нет, это тоже не сработает, потому что это будет соответствовать строке, содержащей только число (т. Е.: это будет соответствовать «42»)
5. какой облом: P но, похоже, Ши Леви опубликовал правильный ответ, не так ли?