Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/402.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 正则表达式精确匹配n个字母和m个数字_Java_Regex - Fatal编程技术网

Java 正则表达式精确匹配n个字母和m个数字

Java 正则表达式精确匹配n个字母和m个数字,java,regex,Java,Regex,我必须匹配一个8个字符的字符串,它可以包含2个字母(1个大写字母和1个小写字母)和6个数字,但它们可以任意排列 因此,基本上: K82v6686将通过 3w28E020将通过 1276eQ900将失败(太长) 98Y78k9k将失败(三个字母) A09B2197将失败(两个大写字母) 我已经尝试使用正向前瞻来确保字符串包含数字、大写和小写字母,但我无法将其限制在一定的出现次数。我想我可以把字母和数字可能出现的所有可能的组合包括在内: (?=.*[0-9])(?=.*[A-Z])(?=.*[a

我必须匹配一个8个字符的字符串,它可以包含2个字母(1个大写字母和1个小写字母)和6个数字,但它们可以任意排列

因此,基本上:

  • K82v6686将通过
  • 3w28E020将通过
  • 1276eQ900将失败(太长)
  • 98Y78k9k将失败(三个字母)
  • A09B2197将失败(两个大写字母)
我已经尝试使用正向前瞻来确保字符串包含数字、大写和小写字母,但我无法将其限制在一定的出现次数。我想我可以把字母和数字可能出现的所有可能的组合包括在内:

(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z]) ([A-Z][a-z][0-9]{6})|([A-Z][0-9][a-z][0-9]{5})| ... | ([0-9]{6}[a-z][A-Z])
但这是一种非常迂回的方法,我想知道是否有更好的解决方案

您可以使用

^(?=[^A-Z]*[A-Z][^A-Z]*$)(?=[^a-z]*[a-z][^a-z]*$)(?=(?:\D*\d){6}\D*$)[a-zA-Z0-9]{8}$
请参阅(由于多行输入而有点修改)。在Java中,不要忘记使用双反斜杠(例如,
\\d
匹配数字)

以下是分项数字:

  • ^
    -字符串的开头(假设不使用多行标志)
  • (?=[^A-Z]*[A-Z][^A-Z]*$)
    -检查是否只有一个大写字母(使用
    \p{Lu}
    匹配任何Unicode大写字母,使用
    \p{Lu}
    匹配除此之外的任何字符)
  • (?=[^a-z]*[a-z][^a-z]*$)
    -如果只有1个小写字母,则进行类似检查(或者,使用
    \p{Ll}
    \p{Ll}
    匹配Unicode字母)
  • (?=(?:\D*\D){6}\D*$)
    -检查字符串中是否有六位数字(=从字符串的开头,可以有0个或更多非数字符号(
    \D
    匹配除数字以外的任何字符,也可以用
    [^0-9]
    )替换,然后后跟数字(
    \D
    )然后后跟0个或多个非数字字符(
    \D*
    ),直到字符串结尾(
    $
    ),然后
  • [a-zA-Z0-9]{8}
    -精确匹配8个字母数字字符
  • $
    -字符串结束
按照逻辑,我们甚至可以将其简化为

^(?=[^a-z]*[a-z][^a-z]*$)(?=(?:\D*\d){6}\D*$)[a-zA-Z0-9]{8}$
可以删除一个条件,因为我们只允许小写和大写字母和数字带有
[a-zA-Z0-9]
,当我们应用两个条件时,在匹配字符串时会自动执行第三个条件(在这种情况下,一个字符必须是大写)

当将其与Java
matches()
方法一起使用时,不需要在模式的开始和结束处使用
^
$
锚定,但在lookaheads中仍然需要它:

String s = "K82v6686";
String rx = "(?=[^a-z]*[a-z][^a-z]*$)" +      // 1 lowercase letter check
            "(?=(?:\\D*\\d){6}\\D*$)" +       // 6 digits check
            "[a-zA-Z0-9]{8}";                 // matching 8 alphanum chars exactly
if (s.matches(rx)) {
    System.out.println("Valid"); 
} 
因为我们需要为这个任务创建一个交替的自动机,所以对字符的组成类型使用regexp的连接要简单得多


我们要求它至少有一个小写字母,一个大写字母和6位数字,这三个类是相互排斥的。在最后一个条件下,我们要求字符串的长度正好是这些数字的总和,这样就不会为超出所需类型的额外字符留出空间。当然,我们可以说
s.lenght()==8
作为最后一个条件项,但这会破坏样式:)。

对字符串进行词汇排序,然后与
^(?[a-z][a-z]|[a-z][a-z])[0-9]{6}$
匹配

你用的是哪种发动机?是否可以将正则表达式拆分为多个测试?i、 除了字母,它是否包含两个字母,如果它包含六个数字呢?我使用的是Java8。字母和数字可以在任何地方。重要的是有6位数字,1个大写字母和1个小写字母。它们在字符串中的位置无关紧要。我可能会编写一个简短的方法来检查这一点(不带正则表达式)。这将更容易理解和维护。我建议您使用此培训工具:我想我们可以将其简化为更短的变体。您能否解释一下(?=(?:\D*\D){6}\D*$)如何检查6位数字?特别是,非捕获组中的\D*是做什么的?我在regex的这一部分添加了解释。实际上,所有的先行条件都基于反向字符类:匹配0个或多个字符,而不是某个字符,然后只匹配某个字符的一个匹配项,指定次数(使用限制量词
{n,m}
)然后匹配除字符串结尾以外的任意数量的字符。谢谢,这是一个非常有用的答案:)只需从第一个解决方案中删除
(?=(?:\D*\D){6}\D*$)
,就可以了。
Pattern.matches(".*[A-Z].*", s) &&
Pattern.matches(".*[a-z].*", s) &&
Pattern.matches(".*(\\D*\\d){6}.*", s) &&
Pattern.matches(".{8}", s)