我有一个类似下面的字符串:
“某些值为25但不得大于12”
我想从字符串中提取两个数字。
数字是整数。
第一个数字之前可能没有文字,第二个数字之后可能没有文字。
我尝试使用正则表达式和群组,但失败了:
public MessageParser(String message) {
Pattern stringWith2Numbers = Pattern.compile(".*(\\d?).*(\\d?).*");
Matcher matcher = stringWith2Numbers.matcher(message);
if (!matcher.matches()) {
couldParse = false;
firstNumber = 0;
secondNumber = 0;
} else {
final String firstNumberString = matcher.group(1);
firstNumber = Integer.valueOf(firstNumberString);
final String secondNumberString = matcher.group(2);
secondNumber = Integer.valueOf(secondNumberString);
couldParse = true;
}
}
任何帮助都是相关的。
答案 0 :(得分:8)
您的模式应该更像:
Pattern stringWith2Numbers = Pattern.compile("\\D*(\\d+)\\D+(\\d+)\\D*");
您需要接受\\d+
,因为它可以是一个或多个数字。
答案 1 :(得分:3)
你的".*"
模式是贪婪的,就像它们常见的那样,并且尽可能地吞噬 - 这将是整个字符串。因此,第一个".*"
匹配整个字符串,使其余部分无法实现。此外,您的"\\d?"
条款表示一个数字恰好是可选的,这两个数字都不是您想要的。
这可能更符合您拍摄的内容:
Pattern stringWith2Numbers = Pattern.compile(".*?(\\d+).*?(\\d+).*?");
当然,既然你在数字之前或之后并不真正关心这些东西,为什么还要烦恼呢?
Pattern stringWith2Numbers = Pattern.compile("(\\d+).*?(\\d+)");
应该这样做。
编辑:从写作屁股踢得非常棒的漫画中抽出时间,艾伦·摩尔在评论中指出了我的解决方案的一些问题。首先,如果字符串中只有一个多位数字,我的解决方案就是错误的。将它应用于“这123是一个坏字符串”将导致它返回“12”和“3”时它应该只是失败。一个更好的正则表达式将规定必须至少有一个非数字字符分隔这两个数字,如下所示:
Pattern stringWith2Numbers = Pattern.compile("(\\d+)\\D+(\\d+)");
此外,matches()
将模式应用于整个字符串,实质上将其括在^
和$
中; find()
可以解决问题,但这不是OP正在使用的。所以坚持matches()
,我们需要在两个数字之前和之后带回那些“无用的”条款。 (虽然让它们明确地匹配非数字而不是通配符是更好的形式。)所以它看起来像:
Pattern stringWith2Numbers = Pattern.compile("\\D*(\\d+)\\D+(\\d+)\\D*");
......必须注意的是,这与jjnguy的回答完全相同。
答案 2 :(得分:2)
你的正则表达式匹配,但是你的第一个.*
会让所有东西都被吃掉,其余的则与空字符串匹配。
将正则表达式更改为"\\D*(\\d+)\\D+(\\d+)\\D*"
。
这应该理解为:至少有一个数字后跟至少一个不是数字的字符,后跟至少一个数字。