3

问题

我希望能够使用单个正则表达式(如果可能)来要求字符串适合[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子域的外观。IEt__t.example.com

4

9 回答 9

8

这完全符合您的要求:

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

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

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

应该可以正常工作。

于 2009-08-06T19:00:30.210 回答
2

我确信您可以将所有这些放入一个正则表达式中,但这并不简单,我不确定为什么坚持将其作为一个正则表达式。为什么不在验证期间使用多次通过?如果在用户创建新帐户时完成了验证检查,那么确实没有任何理由尝试将其塞进一个正则表达式中。(也就是说,您一次只能处理一个项目,而不是数百或数千或更多。我认为,通过正常大小的用户名几次应该花费很少的时间。)

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

于 2009-08-06T18:56:10.747 回答
2

关于什么:

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

它不使用反向引用。

编辑:

成功完成所有测试用例。与红宝石兼容。

于 2009-08-06T19:08:33.813 回答
1

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

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

这是获得所有规则的较长形式:

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

该死,太丑了。我同意 Telemachus 的观点,即您可能不应该使用一个正则表达式来执行此操作,即使它在技术上是可行的。正则表达式通常是维护的痛苦。

于 2009-08-06T18:58:17.313 回答
1

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

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

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

于 2009-08-07T16:32:58.753 回答
0
(?=.*[a-zA-Z].*)^[A-Za-z0-9](_?[A-Za-z0-9]+)*$

这个有效。

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

于 2009-08-06T18:51:01.460 回答
0

干得好:

^(([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] 更改为包含所有允许符号的 []

于 2009-08-06T19:05:33.193 回答
0
/^(?![\d_]+$)[A-Za-z0-9]+(?:_[A-Za-z0-9]+)*$/

您的问题与此问题基本相同,但附加要求至少有一个字符必须是字母。消极的前瞻 -(?![\d_]+$)照顾那部分,并且比其他一些人试图做的那样将它合并到基本的正则表达式中更容易(读取和写入)。

于 2009-08-07T05:00:52.740 回答
-2
[A-Za-z][A-Za-z0-9_]*[A-Za-z]

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

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

于 2009-08-06T18:50:43.113 回答