#ruby-on-rails #ruby #regex #ruby-on-rails-3
#ruby-on-rails #ruby #регулярное выражение #ruby-on-rails-3
Вопрос:
Я некоторое время программировал, но до недавнего времени у меня никогда не было необходимости в регулярных выражениях. Мне нужно создать регулярное выражение, которое принимает имена пользователей, как это делает Twitter. В принципе, я хочу разрешить одно подчеркивание за раз. В имени может быть более одного подчеркивания, но они не должны быть последовательными символами. Буквенно-цифровые символы также разрешены. Но числа не могут начинаться с имени.
Такие имена, как
- _myname67
- myname67
- my_name
- _my_67_name_
допустимы, но
- 94myname
- __myname
- мое__имя
- мое имя
недопустимы.
Я поиграл с Rubular и придумал пару регулярных выражений:
/^[^0-9s ](_?[a-z0-9] _?) $/i
/^([a-z_?]) $/i
Проблема, с которой я продолжаю сталкиваться, заключается в том, что они соответствуют нескольким символам подчеркивания.
Ответ №1:
Отредактировано
a = %w[
_myname67
myname67
my_name
_my_67_name_
94myname
__myname
my__name
my name
m_yname
]
p a.select{|name| name =~ /A_?[a-z]_?(?:[a-z0-9]_?)*z/i}
# => ["_myname67", "myname67", "my_name", "_my_67_name_", "m_yname"]
Вы должны использовать ( )
только для подстрок, которые вы хотите захватить. (?: )
используется для группировок, которые вы не хотите фиксировать. Рекомендуется использовать его всякий раз, когда вам не нужно ссылаться конкретно на эту подстроку. Это также ускоряет выполнение регулярного выражения.
Комментарии:
1. действительно лаконично. но как бы мне ни хотелось проголосовать за это как за правильный ответ, он не соответствует тестовой строке, введенной Грантом Хачатряном, «m_yname». Однако это учит меня чему-то новому. Пожалуйста, объясните выражение ?:, которое у вас есть.
2. В регулярном выражении была проблема, на которую указал Yasky. Я все починил.
3. Как мне включить имена, начинающиеся с цифр, но не разрешать имена, содержащие только цифры?
Ответ №2:
Попробуйте следующее ^([a-zA-Z](_?[a-zA-Z0-9] )*_?|_([a-zA-Z0-9] _?)*)$
Я разделил два случая: слово начинается с буквы и начинается с подчеркивания. Если вы не хотите разрешать имена, состоящие из одного символа, замените только *
на
.
решение maerics имеет одну проблему, оно не фиксирует имена, которые имеют _
второе место, такие как m_yname
Комментарии:
1. 1, но это позволяет использовать имя пользователя
_
, которое не идеально.
Ответ №3:
Некоторые вещи действительно трудно выразить, используя только регулярные выражения, и, как правило, доступны только для записи (то есть, в последнее время нет способа прочитать и понять их). Вы можете использовать более простое регулярное выражение (вроде двух, которые вам удалось написать) и проверить наличие двойных подчеркиваний в вашем Ruby-коде. Это не повредит:
if username =~ /^[^0-9](_?[a-z0-9] _?) $/i and username.count('__') == 0 then ...
Комментарии:
1. Это не работает: несколько символов подчеркивания, которые НЕ являются последовательными, здесь завершатся ошибкой, что не соответствует требованиям OP. (-1)
2. да, но это все равно хороший подход — я отредактировал ответ, чтобы он был username.count(‘__’) > 0, который устраняет дефект, который вы mention…at по крайней мере, если count() работает так, как я предполагаю.
3. Нет, это не так (хотя я тупо проголосовал за одобрение редактирования). Вы хотите, чтобы оно было равно нулю.
4. ха, ну, я просто перередактировал, так как понял, что это все равно странно! Поделом мне за попытку исправить ответ на языке, с которым я не слишком знаком. Я просто сдамся сейчас, я, вероятно, снова облажался: P
5. Да, извините, я просто слишком быстро прочитал сообщение. Исправлено, и спасибо Брайану.
Ответ №4:
Кажется, это работает:
/^(_|([a-z]_)|[a-z])([a-z0-9] _?)*$/i
Обновления: исправлены ограничения на числовые значения и регистр.
Комментарии:
1. Это просто пример, показывающий OP, как справиться с проблемой последовательного подчеркивания.
2. @sawa это проверяет наличие символа подчеркивания или алфавита перед символом подчеркивания или алфавитом только в начальной позиции. Это должно пройти.
3. ‘i’ после регулярного выражения позаботится о нечувствительности к регистру
Ответ №5:
/^[A-Za-z_]([A-Za-z0-9] _?) $/
Комментарии:
1. Бог знает почему. Rubular считает, что это отлично работает, хотя [редактировать — ну, кроме случая с «m_yname», упомянутого Грантом]. Большое спасибо
Ответ №6:
Некоторые проблемы невозможно решить с помощью всего лишь одного регулярного выражения … особенно когда вы хотите проверить отсутствие шаблона, а также наличие другого шаблона.
Иногда лучше (и определенно более читабельно) разбить ваши условия на несколько регулярных выражений и сопоставить с каждым из них по очереди.
В дополнение к вашим регулярным выражениям для проверки правильности символов, вы также должны использовать регулярное выражение для проверки наличия двух знаков подчеркивания, а затем инвертировать этот результат (то есть удалить имя, если оно СООТВЕТСТВУЕТ шаблону).
Комментарии:
1. Или вы можете использовать ответ @sawa, который выполняет эту работу в одном (но гораздо более сложном для чтения) регулярном выражении.
2. Я думаю, ваш ответ подразумевает, что это невозможно сделать с помощью одного регулярного выражения. Во втором предложении у вас есть слово
better
, которое подразумевает, что есть не лучший способ сделать это, но недостаточно сильный, чтобы исключить подтекст первого предложения.3. Справедливое замечание, хотя я думаю, что вы слишком буквальны в своем синтаксическом анализе. Отредактировано.