Regex Ruby正则表达式允许A-Za-z0-9

Regex Ruby正则表达式允许A-Za-z0-9,regex,ruby,Regex,Ruby,我有以下正则表达式: /([A-Za-z0-9]+)([A-Za-z0-9\-\_]+)([A-Za-z0-9]+)/ 它不符合我的需要,这是: 不允许有空格 允许使用大写英文字母 允许使用小写英文字母 允许数字 字符串不能同时包含连字符和下划线 连字符:连字符不能在字符串的开头或结尾; 可以有任意数量的连字符,但连续只能有1个连字符(a--b无效) 下划线:下划线不能在字符串的开头或结尾;可以有任意数量的下划线,但连续只能有1个下划线(a\u\b无效) 字符串必须至少包含1个字符(字母)

我有以下正则表达式:

/([A-Za-z0-9]+)([A-Za-z0-9\-\_]+)([A-Za-z0-9]+)/
它不符合我的需要,这是:

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

  • a1_b_2_你好
  • 2b-ffg-er2
  • abs
  • 123a
无效示例:

  • 你好
  • 2b-ffg\u er2-
  • \u
  • --
  • a\uuu
  • b--2
您可以在中间捕获组之前添加
(?!.*(\-\-\-\\\\\\\\-..*)
,以检查连续的破折号或下划线,并且只在中间捕获组之前添加一种类型,在所有内容之前添加
(?=.[a-z].*)
,以检查至少一个字符。所以整个事情看起来是这样的:

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

您可以在字符类中添加a-zA-Z,并在重复0+次时匹配连字符或下划线
[-\]
,后跟字符类
[a-zA-z0-9]+
中列出的1+次

使用带有的捕获组以获得一致的
-

\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\U c
        ),并将列出的内容匹配1+次
    • )*
      关闭非捕获组并将其设置为可选
  • )?
    关闭非捕获组并将其设置为可选
  • \z
    字符串结尾


有关锚定的详细说明,请参阅。

我发现将所有特殊条件放在开头的正反两种格式中比较方便,并按照一般要求遵循这些条件(不使用字符),这里是
[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(?!.*(?:--|__))(?![-_])(?!.*[-_]\z)(?!.*-.*_|.*_.*-)(?=.*[a-z])[a-z\d_-]+\z/i
使用前向/后向断言的解决方案

举一个你尝试匹配的例子。它和@Thefourhtbird的答案一样有效。非常感谢这通过了我答案中的所有测试,除了第一个测试,当字符串是
“a”
。我想这很容易解决。注
(?=.[a-z].*)
需要包含大写字母,可以简化为
(?=.[a-zA-z])
@caryswovel,OP没有提到长度,idk如果单个字符有效,您说
字符串必须至少包含1个字符,那么
123
如何有效?
a
1
应该是有效的吗?@depperm这是一个描述错误,很好的捕获,
123
是有效的invalid@depperm我把我的推荐贴错了位置,我想问问安德烈·迪内科他想匹配什么,Andrey Deineko给出了一个你尝试的例子,你有一个非常正式的算法,并试图用正则表达式来解决它。我可以问一下为什么吗?“一步一步检查所有条件会有什么问题?”CarySwoveland我按照你的建议编辑了这个问题,谢谢你的回答!这一个匹配的
a-b_c
不应包含在描述中,sorry@AndreyDeineko我已经添加了一个关于模式的解释。这个正则表达式通过了我答案中的所有测试。@AndreyDeineko您可以使用。当捕获组存在时,它将返回捕获组的值。在这种情况下,为了保持反向引用,您可以将整个模式包装在另一个组中,该组将是组1,并使用对内部组2的反向引用<(A-Za-Za-z0-z0-z0-z0-z0-Za-Za-Za-z0-z0-z0-Za-z0-Za-z0-z0-z0-z0-z0-z0-z0-z0-z0-z0-z0-z0-z0-z0-9-9-9-9编码)代码(代码::)目前(代码:)目前(A-A-A-z0-z0-z0-z0-z0-z0-z0-z0-z0-z0-z0-z0-z0-z0-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-9-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-5-"
产生了不正确的结果。啊,我不确定如果
\uu
-
被排除在外是什么意思-字符串不能两者都有。所以你只能有或---我犯了同样的错误。你的答案读起来绝对是一种乐趣,谢谢你,卡里!
/\A(?!.*(?:--|__))(?![-_])(?!.*[-_]\z)(?!.*-.*_|.*_.*-)(?=.*[a-z])[a-z\d_-]+\z/i
^[a-z\d](?!.*--.*)(?!.*__.*)(?!.*-.*_)(?!.*_.*-)[\w-]*(?<=[^_-])$
# 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--_-_--__