代码之家  ›  专栏  ›  技术社区  ›  epochwolf

regex:匹配包含数字和字母的字符串,但不匹配仅包含数字的字符串

  •  3
  • epochwolf  · 技术社区  · 15 年前

    问题

    我希望能够使用一个regex(如果可能)来要求字符串适合 [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不应该发生冲突。

    • γ检验 看起来像Wierd,我不相信它是有效的子域,即 _test.example.com

    • 我不喜欢 塔伊特 作为子域。即 t__t.example.com

    9 回复  |  直到 12 年前
        1
  •  8
  •   Amber    12 年前

    这完全符合您的要求:

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

    编辑:事实上,由于其他regex的工作方式,您可能甚至不需要lookahead/lookbehind——第一个 ?: 在字母数字和第二个字母数字之后,括号才允许下划线。 ?: 加括号不允许下划线,除非它位于字母数字之前:

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

    应该工作得很好。

        2
  •  2
  •   Telemachus MrJames    15 年前

    我相信你 能够 把所有这些放到一个正则表达式中,但这并不简单,我不确定为什么要坚持它是 正则表达式为什么不在验证期间使用多个过程?如果验证检查是在用户创建新帐户时完成的,那么实际上没有任何理由尝试将其塞进一个regex中。(也就是说,您一次只能处理一个项目,而不能处理成百上千个或更多的项目。我想,通过一个正常大小的用户名只需要很少的时间。)

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

        3
  •  2
  •   Sinan Taifour    15 年前

    如何:

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

    它不使用反向引用。

    编辑:

    所有测试用例都成功。与Ruby兼容。

        4
  •  1
  •   Tim    15 年前

    这不会阻止“_uuuuu”,但它会得到其余的:

    ([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的观点,你可能不应该用一个regex来做这个,即使在技术上是可能的。regex通常是维护的难题。

        5
  •  1
  •   glenn mcdonald    15 年前

    这个问题要求一个regexp,并暗示它应该是一个regexp, 比赛 很好,由其他人回答。不过,出于兴趣,我注意到这些规则更容易直接声明为应该 比赛。即。:

    x !~ /[^A-Za-z0-9_]|^_|_$|__|^\d+$/
    
    • 除了字母、数字和_
    • 不能从一开始_
    • 不能以_
    • 一排不能有两个
    • 不能都是数字

    你不能这样在Rails中使用它来验证格式,但是你可以把它放在类的验证方法中,我认为你还是有更好的机会理解你的意思,一个月或一年之后。

        6
  •  0
  •   Rado    15 年前

    干得好:

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

        7
  •  0
  •   Welbog    15 年前
    (?=.*[a-zA-Z].*)^[A-Za-z0-9](_?[A-Za-z0-9]+)*$
    

    这个是有用的。

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

        8
  •  0
  •   Community noseratio    7 年前
    /^(?![\d_]+$)[A-Za-z0-9]+(?:_[A-Za-z0-9]+)*$/
    

    你的问题本质上与 this one ,还要求至少有一个字符必须是字母。消极的展望- (?![\d_]+$) -处理好这一部分,并且比像其他一些regex所做的那样将它合并到基本regex中要容易得多(读和写)。

        9
  •  -2
  •   rpjohnst    15 年前
    [A-Za-z][A-Za-z0-9_]*[A-Za-z]
    

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

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