Java 从字符串中提取两个数字

Java 从字符串中提取两个数字,java,regex,Java,Regex,我有一个字符串,如下所示: “某些值为25,但不得大于12” 我想从字符串中提取这两个数字 这些数字是整数 第一个数字前可能没有文本,第二个数字后可能有一些文本 我试图用regexp和groups来实现这一点,但失败得很惨: public MessageParser(String message) { Pattern stringWith2Numbers = Pattern.compile(".*(\\d?).*(\\d?).*"); Matcher matcher = stri

我有一个字符串,如下所示:

“某些值为25,但不得大于12”

我想从字符串中提取这两个数字

这些数字是整数

第一个数字前可能没有文本,第二个数字后可能有一些文本

我试图用regexp和groups来实现这一点,但失败得很惨:

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;
    }
}

非常感谢您的帮助。

您的模式应该更像:

Pattern stringWith2Numbers = Pattern.compile("\\D*(\\d+)\\D+(\\d+)\\D*");

您需要接受
\\d+
,因为它可以是一个或多个数字。

您的正则表达式匹配,但所有内容都被第一个
*
占用,其余的匹配空字符串

将正则表达式更改为
“\\D*(\\D+)\\D+(\\D+)\\D*”

这应该被理解为:至少一个数字后跟至少一个非数字字符,后跟至少一个数字。

您的
“*”
模式正在贪婪,这是他们的习惯,并且正在尽可能多地吞噬——这将是整个字符串。因此,第一个
“*”
匹配整个字符串,使得其余的字符串没有意义。另外,您的
“\\d?”
子句表示一个恰好是可选的单个数字,这两个数字都不是您想要的

这可能更符合您的拍摄目的:

Pattern-stringWith2Numbers=Pattern.compile(“.*?(\\d+).*?(\\d+).*”

当然,既然你真的不在乎数字之前或之后的东西,为什么还要麻烦它们呢

Pattern-stringWith2Numbers=Pattern.compile(“(\\d+).*?”(\\d+)

这应该能奏效

编辑:艾伦·摩尔花了一点时间写了一些非常棒的漫画,他在评论中指出了我的解决方案存在的一些问题。首先,如果字符串中只有一个多位数,我的解决方案就会出错。将它应用于“this123是一个坏字符串”将导致它在应该失败时返回“12”和“3”。更好的正则表达式将规定两个数字之间必须至少有一个非数字字符,如下所示:

Pattern-stringWith2Numbers=Pattern.compile(“(\\d+)\\d+”(\\d+)

另外,
matches()
将模式应用于整个字符串,基本上将其括在
^
$
find()
会起作用,但OP并没有这么做。因此,坚持使用
matches()
,我们需要在这两个数字之前和之后引入那些“无用”子句。(虽然让它们显式地匹配非数字而不是通配符是更好的形式。)因此它看起来像:

Pattern-stringWith2Numbers=Pattern.compile(\\D*(\\D+)\\D+(\\D+)\\D*)


。。。必须指出的是,这与JNGUY的答案几乎相同。

数字模式之间的“*”会不会“吃掉”第二个数字?不会。星号后面的问号表示它应该匹配尽可能短的字符串——因此,它将匹配第二个数字之前的所有内容。。。。虽然,因为两位数的子句不再是可选的,问号就不那么重要了——如果您完全确定字符串中有两个且只有两个数字,那么就不需要问号了。不过,如果有更多的数字,这很重要。使用“1、2和3”作为示例字符串:使用问号,您将得到1和2。如果没有,1和3将是两个提取的值。您可以通过使用
\\D*
而不是像@jinguy那样使用
*
来避免该问题。但是中间的一个应该是<代码> \d+<代码>,正如我在评论中对他的回答所解释的。我没有想到,但是你是对的;如果输入文本中真的有两个数字,我的解决方案就可以了,但是如果文本是“我有一个42号”,当它应该失败时,它将返回“4”和“2”。我甚至没有想到比赛/发现的事情,这在过去让我绊倒了。将编辑答案,因为尽管存在这些缺陷,答案还是被接受了。:-)\D*(\D+)^\D]*(\D+)^\D*不是更合适吗?因为我们明确地不需要数字和。有可能在到达\d之前匹配一个数字。第二个
\\d*
应该是
\\d+
。实际上,您的正则表达式可以匹配字符串
“42”
,将
“4”
保留在组1中,将
“2”
保留在组2中。如果在OP中使用
匹配()
方法,则必须使用前导和尾随
*
。您的正则表达式将使用
find()
方法,该方法执行更传统的“它在某处”正则表达式匹配。