Java 仅允许一组字符中的1个的正则表达式

Java 仅允许一组字符中的1个的正则表达式,java,regex,Java,Regex,我试图使用一些正则表达式来验证Java代码内部的一些输入。我已经成功地实现了“basic”regex,但是这个似乎超出了我的知识范围。我正在通过RegEgg教程学习更多内容 以下是需要验证的条件: 字段将始终有8个字符 可以是所有空间 或 有效字符:a-zA-Z0-9-!&还是一个空间 不能以空格开头 如果使用了其中一个特殊字符,则只能使用该字符 法律:“B-123----”AB&&&&“A!!!!!!!” 非法:“B-123!!!”“AB&&-”“A&!” 必须至少有一个字母数字字符(不

我试图使用一些正则表达式来验证Java代码内部的一些输入。我已经成功地实现了“basic”regex,但是这个似乎超出了我的知识范围。我正在通过RegEgg教程学习更多内容

以下是需要验证的条件:

  • 字段将始终有8个字符
  • 可以是所有空间

  • 有效字符:a-zA-Z0-9-!&还是一个空间
  • 不能以空格开头
  • 如果使用了其中一个特殊字符,则只能使用该字符 法律:“B-123----”AB&&&&“A!!!!!!!” 非法:“B-123!!!”“AB&&-”“A&!”
  • 必须至少有一个字母数字字符(不能都是特殊字符,例如:“!!!!!!!!!”
在添加其他验证之前,这是我的正则表达式:

^(\s{8}|[A-Za-z\-\!\&][ A-Za-z0-9\-\!\&]{7})$"
现在的附加验证允许使用多个特殊字符,我有点卡住了。我已经成功地使用了正向前瞻,但在尝试使用正向前瞻时卡住了。(我认为在使用前瞻之前的数据),但我在猜测,因为我是正则表达式这一部分的新手。

使用or构造(
a | b
)是其中的一大部分,您已经开始应用它,所以这是一个好的开始

您已经制定了规则,它不能以数字开头;规范中没有这样的规定。而且,
-
内部的
[]
具有特殊意义,所以请将其转义,或者确保它是第一个或最后一个,因为这样您就不必这样做。这让我们:

^(\s{8}|[A-Za-z0-9-!&-]{8})$

下一个规则是,如果使用所有特殊字符,它必须是所有相同的特殊字符。鉴于只有3个特殊字符,只需显式列出它们就更容易了:

^(\s{8}|[A-Za-z0-9-]{8}|[A-Za-z0-9!]{8}|[A-Za-z0-9&]{8})$

下一步:不能以空格开头,也不能全部是特殊字符。确认否定字符(并非所有特殊字符)会变得复杂;在这里,向前看似乎是一个更好的计划。这是:

^
是regexp-ese,表示“行开始”。请注意,这并不“使用”字符。
1
是regexpse,表示“此处仅匹配确切的字符“1”,其他任何字符都不匹配”,但当它匹配时,它也“使用”该字符,而
^
不这样做。“行开始”不是一个可以使用的概念

“匹配可能失败,但如果成功,则不会消耗任何东西”的概念不仅限于
^
$
;您可以编写自己的:

(?=abc)
将匹配,如果
abc
将匹配此位置,但不使用它。因此,regexp
^(=abc)ab.d$
将匹配输入字符串
abcd
,而不匹配任何其他内容。这称为正向前瞻。(如果在parens中看到正则表达式,它会“向前看”并匹配,如果没有,则会失败)

(?!abc)
负前瞻性的。如果在参数中看不到内容,则匹配。
(?!abc)a.c
将匹配输入
adc
,但不匹配输入
abc

(?负向后看

请注意,lookahead和lookahead可能有一定的限制,因为它们可能不允许可变长度的模式。但是,幸运的是,您的需求使我们很容易将自己限制为固定大小的模式。因此,我们可以介绍:
(?![&!-]{8})
作为我们的regexp中的非消耗单元,如果我们有全部8个特殊字符,将导致匹配失败

我们也可以使用这个技巧在起始空间失败:
(?!)
就是我们所需要的

让我们将
\s
这一空白替换为
,这是空格字符(问题描述是“空格”,而不是“空白”)

总而言之:

^({8}|(?!)(?![&!-]{8})([A-Za-z0-9-]{8}|[A-Za-z0-9!]{8}|[A-Za-z0-9&]{8}])$

那就是:

  • 8个空格,或
  • 不是空格,也不是全部8个特殊字符
  • 任何有效字符,任何数量的空格,以及任何数量的3个允许的特殊符号之一,只要我们正好有8个
  • …或与#3相同,但带有三个特殊符号中的第二个
  • …或是三个中的第三个
  • 将它们与您的各种“合法”和“不合法”示例一起插入,您可以进一步使用它们


    注意:您也可以使用反向引用来尝试解决其中的“仅允许一个特殊字符”部分,但是如果您不使用(负)前瞻,则尝试解决“并非所有特殊字符”部分似乎相当笨拙。

    这是一个在正则表达式开始时断言正确条件的问题

    ^(?=[]*$|(?![])(?!!.([!&-])。(?!!!&-])。(?!!!&-])[a-zA-Z0-9!&-]{8}$

    见->

    一些讨论:

     ^                      # Begin of text
     (?=                    # Assert, cannot start with a space
          [ ]* $            # unless it's all spaces
       |  (?! [ ] )
     )
     (?!                    # Assert, not mixed special chars
          .* 
          ( [!&-] )         # (1)
          .* 
          (?! \1 )
          [!&-] 
     )
     [a-zA-Z0-9 !&-]{8}     # Consume 8 valid characters from within this class
     $                      # End of text
    

    您是否可以单独运行两个正则表达式,然后使用一个条件来确定是否触发了一个或另一个正则表达式?即使这不能解决问题,它也会简化它(可能是第二个更棘手的情况)。既然您已经描述了一个有效的集合,那么您还可以包括无效的集合吗?因为有时有效与必需同义。一旦您了解了如何使用正则表达式执行此操作,您可能会认为使用普通Java代码强制执行约束要简单得多。我非常感谢您!这不仅是为了一个有效的解决方案,也是为了一个出色的正则表达式刨削。这有助于我的学习!谢谢!仅供参考…上面的正则表达式有一个问题…它允许:!!!!!如果不是所有空格,字符串中必须至少有一个字母数字。我通过执行以下操作来修复它:^({8}|(?=.[a-zA-Z0-9].(?![0-9])(?![&-]{8}([a-zA Z0-9-]{8}{a-zA Z0 9!]又一次,谢谢你!我得学着怎么做