我想检查一个字符串是否只包含一个数字,如果它包含多个数字,则引发异常:
(D*?\d+\D+\d+D*)
private static void assertOnlyOneNumber(String input) {
if (input.matches(("(D*?\d+\D+\d+D*)"))) {
throw new RuntimeException(
"Assertion failed! String contains more than a single number: "
+ input);
}
}
因此,例如,以下内容应匹配并抛出异常:
- 42'12
- 1小时22分钟
- 01:23:22
- 约120分钟、200分钟、300分钟
以下内容不应匹配,因此被视为有效:
- 12 分钟
- 141'
- 约22分钟
看起来我的正则表达式工作正常,但很容易出错,因此我的问题。
背景:基本上,我从字符串字段转换为整数字段,我将字符串字段解释为以分钟为单位的持续时间。因此,我首先运行此检查以确保字符串中不超过一个数字,然后我剥离一个固定的已知标记数组(如"分钟"、"分钟"等),最后尝试通过 Integer.parseInt() 如果我可以转换它。
如果是,我的持续时间以分钟为单位,否则我会抛出异常。
如果你想保留在一行中,你仍然可以简单地将正则表达式简化为.*\d\D+\d.*
。
但是,进行多次检查可能会更容易,特别是如果您想将其更改为"不超过 x 个数字":
Matcher m = Pattern.compile("\d+").matcher(input);
for (int i = 0; i < allowedNumber; i++)
m.find();
if (m.find())
throw new RuntimeException(...);
两种方式之间的合并是根据允许的出现次数构建正则表达式:
String regex = Stream.generate(() -> "\d+").limit(allowedNumber + 1).collect(joining("\D+", ".*", ".*"))
// non-stream equivalent
String regex = ".*\d+";
for (int i = 0; i < allowedNumber; i++) {
regex += "\D+\d+";
}
regex += ".*";
if (input.matches(regex)) {
throw new RuntimeException(...);
}
您可以使用:
private static void assertOnlyOneNumber(String input) {
if (input.matches(".*\d+\D+\d.*")) {
throw new RuntimeException(
"Assertion failed! String contains more than a single number: "
+ input);
}
}
正则表达式演示
正则表达式.*\d+\D+\d.*
将匹配至少 2 组数字的输入。
这应该有效:
private static final Pattern NUMBER_PATTERN = Pattern.compile("\d+");
private static void assertOnlyOneNumber(String input) {
Matcher m = NUMBER_PATTERN.matcher(input);
int count = 0;
while(m.find()) count++;
// != 1 ensure that the input contains exactly one number (not more, not less)
// if "not more than one" is the intended behaviour just use > 1
if(count != 1) {
throw new RuntimeException(
"Assertion failed! String contains more than a single number: "
+ input);
}
}
试试这个:
(?:d+(?:[^dn]|$)+?){2,}
解释:
// Matches group composed of
(?:d+ // number and
(?:[^dn]| // not number OR
$)+? // end of line
) {2,} // at least two times
演示