【问题标题】:Ruby regex to allow A-Za-z0-9Ruby 正则表达式允许 A-Za-z0-9
【发布时间】:2019-12-17 09:31:09
【问题描述】:

我有以下正则表达式:

/([A-Za-z0-9]+)([A-Za-z0-9\-\_]+)([A-Za-z0-9]+)/

它不符合我的需要,它们是:

  • 不允许有空格
  • 允许大写英文字母
  • 允许小写英文字母
  • 允许数字
  • 字符串不能同时包含连字符和下划线
  • 连字符:连字符不能在字符串的开头或结尾; 可以有任意数量的连字符,但连续只能有 1 个连字符(a--b 无效)。
  • 下划线:下划线不能在字符串的开头或结尾;可以有任意数量的下划线,但连续只能有 1 个下划线(a__b 无效)
  • 字符串必须至少包含 1 个字符(字母)

有效例子:

  • a1_b_2_hello
  • 2b-ffg-er2
  • abs
  • 123a

无效示例:

  • _a1_b_2_hello
  • 2b-ffg_er2-
  • __
  • --
  • a__
  • b--2

【问题讨论】:

  • 你说the string must contain at least 1 character,那么123 是如何有效的呢? a1 应该是有效的吗?
  • @depperm 描述有误,不错,123 无效
  • @depperm 我在错误的帖子中发表了我的推荐,我想问 Andrey Deineko 他尝试匹配什么,Andrey Deineko 举个例子你尝试匹配什么
  • 你有一个非常正式的算法,并试图用正则表达式来解决它。我可以问为什么吗?检查所有条件一步一步会有什么问题?
  • @CarySwoveland 我按照你的建议编辑了问题,谢谢

标签: regex ruby


【解决方案1】:

我发现将所有特殊条件放在正面和负面的前瞻中很方便,并按照一般要求遵循这些(不消耗任何字符),这里是[a-z\d_-]+\z

r = /
    \A           # match start of string  
    (?!.*        # begin negative lookahead and match >= 0 characters
      (?:--|__)  # match -- or __ in a non-capture group
    )            # end negative lookahead
    (?![-_])     # do not match - or _ at the beginning of the string
    (?!.*[-_]\z) # do not match - or _ at the end of the string
    (?!          # begin negative lookahead
      .*-.*_     # match - followed by _ 
      |          # or
      .*_.*-     # match _ followed by - 
    )            # end negative lookahead
    (?=.*[a-z])  # match at least one letter 
    [a-z\d_-]+   # match one or more English letters, digits, _ or -
    \z           # match end of string
    /ix          # case indifference and free-spacing modes

 "a".match? r          #=> true   
 "aB32-41".match? r    #=> true
 "".match? r           #=> false (must match a letter)
 "123-4_5".match? r    #=> false (must match a letter)
 "-aB32-4_1".match? r  #=> false (cannot begin with -)
 "aB32-4_1-".match? r  #=> false (cannot end with -)
 "_aB32-4_1".match? r  #=> false (cannot begin with _)
 "aB32-4_1_".match? r  #=> false (cannot end with _)
 "aB32--4_1".match? r  #=> false (cannot contain --)
 "aB32-4__1".match? r  #=> false (cannot contain __)
 "aB32-4_1".match? r   #=> false (cannot contain both - and _)
 "123-4_5$".match?  r  #=> false ($ is not a permitted character)

这个正则表达式按惯例写成:

/\A(?!.*(?:--|__))(?![-_])(?!.*[-_]\z)(?!.*-.*_|.*_.*-)(?=.*[a-z])[a-z\d_-]+\z/i

【讨论】:

  • 您的回答总是令人愉悦,谢谢您,Cary!
【解决方案2】:

您可以在字符类中添加 a-zA-Z,并且在 0+ 次重复中匹配连字符或下划线 [-_] 后跟字符类 [A-Za-z0-9]+ 中列出的内容的 1+ 倍.

使用带有backreference 的捕获组来获得-_ 的一致使用

\A[A-Za-z0-9]*[A-Za-z][A-Za-z0-9]*(?:([-_])[A-Za-z0-9]+(?:\1[A-Za-z0-9]+)*)?\z

关于模式

  • \A 字符串开始
  • [A-Za-z0-9]*[A-Za-z][A-Za-z0-9]* 至少匹配 1 个 a-zA-Z
  • (?:非捕获组
    • ([-_]) 捕获组 1,匹配 -_
    • [A-Za-z0-9]+ 匹配所列内容的 1 次以上
    • (?:
      • \1[A-Za-z0-9]+ 反向引用 \1 到第 1 组中捕获的内容以获得一致的分隔符(以防止匹配 a-b_c)并匹配所列内容的 1 倍以上
    • )*关闭非捕获组并使其可选
  • )?关闭非捕获组并使其可选
  • \z字符串结束

Regex demo

有关锚点的详细说明,请参阅this page

【讨论】:

  • 感谢您的回答!这个匹配 a-b_c regex101.com/r/aY5Doc/2 不应该
  • 正在编辑描述,抱歉
  • @AndreyDeineko 我已经添加了关于模式的解释。
  • 这个正则表达式通过了我答案中的所有测试。
  • @AndreyDeineko 你可以使用regexp_matches。当它存在时,它将返回捕获组的值。在这种情况下,为了保持反向引用,您可以将整个模式包装在另一个组中,然后将其作为组 1 并使用对内部组 2 的反向引用。^([A-Za-z0-9]*[A-Za-z][A-Za-z0-9]*(?:([-_])[A-Za-z0-9]+(?:\2[A-Za-z0-9]+)*)?$)')Regex demopostgress demo
【解决方案3】:

您可以添加(?!.*(\-\-|__|_.*\-|\-.*_).*),以检查连续的破折号或下划线,并且在中间捕获组之前只检查一种类型,并在所有内容之前添加(?=.*[a-z].*),以检查至少一个字符。所以整个事情看起来像:

(?=.*[a-zA-Z].*)([A-Za-z0-9]+)(?!.*(\-\-|__|_.*\-|\-.*_).*)([A-Za-z0-9\-\_]+)([A-Za-z0-9]+)

【讨论】:

  • 举个例子你尝试匹配什么。
  • 它和@Thefourhtbird 的回答一样有效。非常感谢
  • 当字符串为"a" 时,这通过了我答案中的所有测试,除了第一个测试。我希望这是一个简单的修复。注意(?=.*[a-z].*)需要包含大写字母,可以简化为(?=.*[a-zA-Z])
  • @CarySwoveland OP 没有提及长度,如果单个字符有效,则为 idk
【解决方案4】:

使用前瞻/后瞻断言的解决方案

^[a-z\d](?!.*--.*)(?!.*__.*)(?!.*-.*_)(?!.*_.*-)[\w-]*(?<=[^_-])$

Click here to see demo

  • ^[a-z\d] - 以任何字母或数字开头
  • (?!.*--.*)(?!.*__.*) - 提前确保没有 __ 或 --
    • (?!.*-.*_)(?!.*_.*-) - 向前看以确保没有_,然后是-,反之亦然
  • [\w-]* - 可选择匹配任何字母、数字、_-
  • (?&lt;=[^_-]) - 回顾以确保它不以 - 或 _ 结尾

样本数据:

# Start with a letter
a
ab
abc
abc123
abc123abc

# Has underscores
a_b
a_b_c

# Has dashes
a-b
a-b-c

# Can't start or end with an underscore or dash
_abc
abc_
abc-
-abc

# Can't contain -- or __
a__
a__b
a__b__c
d--
d--e
a--b--c

# Can only use _ or - but not both

a-_b
a-_b-_c
a-_b_-d
a-_b_____f--_-_--__

【讨论】:

  • 如果您针对我的答案中的示例测试您的正则表达式,您会发现 "a""123-4_5""aB32--4_1""aB32-4__1""aB32-4_1""123-4_5$" 产生不正确的结果。
  • 啊,我不确定如果 _- 被排除在外是什么意思 - 字符串不能同时包含两者。所以你只能有 _ 或 - -- 明白了
  • 我也犯了同样的错误。
猜你喜欢
  • 2015-01-07
  • 1970-01-01
  • 2021-11-09
  • 2010-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多