Что такое регулярное выражение для имен, похожих на Twitter?

#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. Справедливое замечание, хотя я думаю, что вы слишком буквальны в своем синтаксическом анализе. Отредактировано.