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

我希望能够使用单个正则表达式(如果可能)要求字符串适合[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

这完全符合您的要求:

 /\A(?!_)(?:[a-z0-9]_?)*[az](?:_?[a-z0-9])*(? 
  1. 至少一个字母字符(中间的[az] )。
  2. 不以下划线开头或结尾(开头和结尾的(?!_)(? )。
  3. 字母字符前后可以包含任意数量的数字,字母或下划线,但每个下划线必须至少用一个数字或字母(其余部分)分隔。

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

 /\A(?:[a-z0-9]_?)*[az](?:_?[a-z0-9])*\z/i 

应该工作正常。

我确信你可以将所有这些放在一个正则表达式中,但这并不简单,我不确定为什么坚持它是一个正则表达式。 为什么不在validation期间使用多次传递? 如果在用户创建新帐户时完成validation检查,则没有任何理由尝试将其填充到一个正则表达式中。 (也就是说,你只会一次处理一个项目,而不是数百或数千或更多。对于正常大小的用户名,几次传递应该花很少的时间,我想。)

如果名称不包含至少一个数字,则首先拒绝; 如果名称不包含至少一个字母,则拒绝; 然后检查开始和结束是否正确; 这些传递中的每一个都可以是易于阅读和易于维护的正则表达式。

关于什么:

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

它不使用后向引用。

编辑:

成功完成所有测试用例。 ruby是否兼容。

这不会阻止“__”,但它确实得到了其余的:

 ([A-Za-z]|[0-9][0-9_]*)([A-Za-z0-9]|_[A-Za-z0-9])* 

这是获得所有规则的更长forms:

 ([A-Za-z]|([0-9]+(_[0-9]+)*([A-Za-z|_[A-Za-z])))([A-Za-z0-9]|_[A-Za-z0-9])* 

dang,那很难看。 我同意Telemachus,你可能不应该用一个正则表达式做这个,即使它在技术上是可行的。 正则表达式通常是维护的痛苦。

这个问题要求一个正则表达式,并暗示它应该是匹配的正则表达式,这很好,并且由其他人回答。 但是,为了兴趣,我注意到这些规则更容易直接表示为匹配的正则表达式。 即:

 x !~ /[^A-Za-z0-9_]|^_|_$|__|^\d+$/ 
  • 除了字母,数字和_之外没有其他字符
  • 不能以_开头
  • 不能以_结尾
  • 不能连续两个_s
  • 不能全部数字

你不能在Rails validates_format_of中以这种方式使用它,但你可以将它放在类的validation方法中,我认为你有更好的机会仍然能够理解你的意思,一个月或从现在起一年。

干得好:

 ^(([a-zA-Z]([^a-zA-Z0-9]?[a-zA-Z0-9])*)|([0-9]([^a-zA-Z0-9]?[a-zA-Z0-9])*[a-zA-Z]+([^a-zA-Z0-9]?[a-zA-Z0-9])*))$ 

如果要限制要接受的符号,只需使用包含所有允许符号的[]更改所有[^ a-zA-Z0-9]

 (?=.*[a-zA-Z].*)^[A-Za-z0-9](_?[A-Za-z0-9]+)*$ 

这个有效。

向前看以确保字符串中至少有一个字母,然后开始消耗输入。 每次有下划线时,下一个下划线前必须有一个数字或一个字母。

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

您的问题基本上与此问题相同,并且要求至少有一个字符必须是字母。 负向前瞻 – (?![\d_]+$) – 负责处理那部分,并且比其他人试图做的更容易(包括读写),而不是将其纳入基本正则表达式。

 [A-Za-z][A-Za-z0-9_]*[A-Za-z] 

这适用于你的前两个规则(因为它需要一个字母在开头和结尾为第二个规则,它自动需要字母)。

我不确定第三条规则是否可以使用正则表达式。