正则表达式:匹配包含数字和字母的字符串,但不包含只是数字的字符串

epo*_*olf 3 ruby regex puzzle ruby-on-rails

我希望能够使用单个正则表达式(如果可能)要求字符串适合[A-Za-z0-9_]但不允许:

  • 字符串只包含数字或/和符号.
  • 以符号开头或结尾的字符串
  • 彼此相邻的多个符号

有效

  • test_0123
  • t0e1s2t3
  • 0123_test
  • te0_s1t23
  • t_t

无效

  • t__t
  • ____
  • 01230123
  • _0123
  • _test
  • _test123
  • test_
  • test123_

规则的原因

这样做的目的是过滤我正在处理的网站的用户名.出于特定原因,我已达到规则.

  • 仅包含数字和/或符号的用户名可能会导致路由和数据库查找出现问题./users/#{id}允许的路由id是用户的id或用户的名称.所以名称和ID不应该碰撞.

  • _test 看起来很奇怪,我不相信它是有效的子域名,即 _test.example.com

  • 我不喜欢t__t作为子域的外观.即t__t.example.com

Amb*_*ber 8

这完全符合您的要求:

/\A(?!_)(?:[a-z0-9]_?)*[a-z](?:_?[a-z0-9])*(?<!_)\z/i
Run Code Online (Sandbox Code Playgroud)
  1. 至少一个字母字符([a-z]中间).
  2. 没有开始或下划线(结束(?!_)(?<!_)在开头和结尾).
  3. 字母字符前后可以包含任意数量的数字,字母或下划线,但每个下划线必须至少用一个数字或字母(其余部分)分隔.

编辑:事实上,由于正则表达式的其余部分如何工作,你甚至可能根本不需要前瞻/后看 - 第一个?:括号不会允许下划线直到字母数字后,第二个?:括号将不允许下划线除非是在字母数字之前:

/\A(?:[a-z0-9]_?)*[a-z](?:_?[a-z0-9])*\z/i
Run Code Online (Sandbox Code Playgroud)

应该工作正常.