正则表达式精确匹配n个字母出现和m个数字出现 [英] Regex to match exactly n occurrences of letters and m occurrences of digits
问题描述
我必须匹配8个字符串,该字符串可以包含正好2个字母(1个大写字母和1个小写字母)以及正好6个数字,但是可以任意排列.
I have to match an 8 character string, which can contain exactly 2 letters (1 uppercase and 1 lowercase), and exactly 6 digits, but they can be permutated arbitrarily.
所以,基本上:
- K82v6686会通过
- 3w28E020会通过
- 1276eQ900将失败(时间太长)
- 98Y78k9k会失败(三个字母)
- A09B2197会失败(两个大写字母)
我尝试使用正向查找来确保该字符串包含数字,大写和小写字母,但是在将其限制为一定数量的出现时遇到了麻烦.我想我可以通过包括字母和数字可能出现的位置的所有可能组合来解决此问题:
I've tried using the positive lookahead to make sure that the string contains digits, uppercase and lowercase letters, but I have trouble with limiting it to a certain number of occurrences. I suppose I could go about it by including all possible combinations of where the letters and digits can occur:
(?=.*[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])
但这是一种非常round回的方式,我想知道是否有更好的解决方案.
But that's a very roundabout way of doing it, and I'm wondering if there's a better solution.
推荐答案
您可以使用
^(?=[^A-Z]*[A-Z][^A-Z]*$)(?=[^a-z]*[a-z][^a-z]*$)(?=(?:\D*\d){6}\D*$)[a-zA-Z0-9]{8}$
请参见 regex演示(由于多行输入而有所修改).在Java中,请不要忘记使用双反斜杠(例如 \\ d
来匹配数字).
See the regex demo (a bit modified due to the multiline input). In Java, do not forget to use double backslashes (e.g. \\d
to match a digit).
以下是细分:
-
^
-字符串的开头(假设不使用多行标志) -
(?= [^ AZ] * [AZ] [^ AZ] * $)
-检查是否只有1个大写字母(使用\ p {Lu}
可以匹配任何Unicode大写字母,而\ P {Lu}
可以匹配任何其他字符) -
(?= [^ az] * [az] [^ az] * $)
-类似检查是否只有1个小写字母(或者,使用\ p {Ll}
和\ P {Ll}
以匹配Unicode字母) -
(?=(?:\ D * \ d){6} \ D * $)
-检查字符串中是否有六位数字(=从字符串开头开始,可以是0个或多个非数字符号(\ D
可以匹配除数字以外的任何字符,您也可以将其替换为[^ 0-9]
),然后跟一个数字(\ d
),然后是0或多个非数字字符(\ D *
),直到字符串的末尾($
>)),然后 -
[a-zA-Z0-9] {8}
-精确匹配8个字母数字字符. -
$
-字符串的结尾.
^
- start of string (assuming no multiline flag is to be used)(?=[^A-Z]*[A-Z][^A-Z]*$)
- check if there is only 1 uppercase letter (use\p{Lu}
to match any Unicode uppercase letter and\P{Lu}
to match any character other than that)(?=[^a-z]*[a-z][^a-z]*$)
- similar check if there is only 1 lowercase letter (alternatively, use\p{Ll}
and\P{Ll}
to match Unicode letters)(?=(?:\D*\d){6}\D*$)
- check if there are six digits in a string (=from the beginning of the string, there can be 0 or more non-digit symbols (\D
matches any character but a digit, you may also replace it with[^0-9]
), then followed by a digit (\d
) and then followed by 0 or more non-digit characters (\D*
) up to the end of string ($
)) and then[a-zA-Z0-9]{8}
- match exactly 8 alphanumeric characters.$
- end of string.
按照逻辑,我们甚至可以将其简化为
Following the logic, we can even reduce this to just
^(?=[^a-z]*[a-z][^a-z]*$)(?=(?:\D*\d){6}\D*$)[a-zA-Z0-9]{8}$
可以删除一个条件,因为我们只允许使用 [a-zA-Z0-9]
大小写字母和数字,而当我们应用2个条件时,第三个条件将自动执行 matching 字符串(在这种情况下,一个字符必须是大写).
One condition can be removed as we only allow lower- and uppercase letters and digits with [a-zA-Z0-9]
, and when we apply 2 conditions the 3rd one is automatically performed when matching the string (one character must be an uppercase in this case).
与Java matches()
方法一起使用时,无需在<开始>和结束时使用 ^
和 $
锚模式,但您仍需要在前瞻中使用它:
When using it with Java matches()
method, there is no need to use ^
and $
anchors at the start and end of the pattern, but you still need it in the 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");
}
这篇关于正则表达式精确匹配n个字母出现和m个数字出现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!