Java:如何从正则表达式中解析double

23

我有一个字符串,它看起来像是 "A=1.23;B=2.345;C=3.567"。

我只对 "C=3.567" 感兴趣。

目前为止,我所拥有的是:

     Matcher m = Pattern.compile("C=\\d+.\\d+").matcher("A=1.23;B=2.345;C=3.567");

    while(m.find()){ 
        double d = Double.parseDouble(m.group());
        System.out.println(d);
    }

问题是它将3和567分别显示。

输出:

3.0

567.0

我想知道如何包含小数点,输出"3.567"。

编辑:如果C没有小数点,我也想匹配C: 因此,我希望能够捕获3567以及3.567。

由于C=也被构建到模式中,所以我该如何在解析double之前将其删除?


2
一个句点(".")不是数字。 - user166390
5个回答

42

我在这部分可能错了,但之所以会将它们分开是因为group()只能匹配最后一次匹配的子序列,也就是每次调用find()所匹配的内容。谢谢,Mark Byers。

当然,你可以通过将想要匹配的整个部分放入"捕获组"中来解决此问题。这可以通过将其放在括号中实现。这样可以将正则表达式的匹配部分分组成一个子字符串。因此,您的模式看起来应该像:

Pattern.compile("C=(\\d+\\.\\d+)")

对于解析3567或3.567,您的模式将为 C=(\\d+(\\.\\d+)?) 其中第1组表示整数。还要注意,由于您特别想匹配一个句点,因此您需要转义句点(period)字符,以使其不被解释为“任意字符”令牌。但是对于这个输入并不重要。

然后,要获取您的3.567,您需要调用m.group(1)来获取指定组中的第一项(从1开始计数)。这意味着您的Double.parseDouble调用实质上将变为Double.parseDouble("3.567")

至于从您的模式中去掉C=,由于我对RegExp不是很熟悉,我建议您在分号上拆分您的输入字符串,然后检查每个拆分是否包含C; 然后您可以应用该模式(具有捕获组),以从您的Matcher中获取3.567。

编辑 对于gawi评论中更一般(也可能更有用!)的情况,请使用以下内容(来自 http://www.regular-expressions.info/floatingpoint.html

Pattern.compile("[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?")

这个正则表达式支持可选符号,可选整数或小数部分,以及可选的正负指数。根据需要插入捕获组来单独选出各个部分。指数作为一个整体在自己的组中,使其整体上是可选的。


1
注意:正则表达式无法处理以下浮点数:10 10. .1 1.3e10 1.2e-12 1.41e+12 - gawi
@gawi 谢谢 :) 我已经更新了答案,加入了一个正则表达式,应该可以解决问题。10.被认为是一个有效的浮点数吗,带有小数点但没有小数位? - Brian
1
10.f 是 Java 中有效的浮点字面量(确切地说是 10.f)。 - gawi
1
我不明白为什么你认为使用 group() 与问题有关。他的正则表达式中没有任何额外的组。 - Mark Byers
@Mark Byers,我猜这表明在回复和误读javadocs之前,我应该先尝试他的代码。我刚刚运行了OP的代码,它没有产生提到的相同结果(获取两个单独的匹配)。感谢您的帮助:) - Brian
1
你的答案仍然不支持10.。我已经根据@gawi的要求进行了调整。[-+]?([0-9]+\\.?[0-9]*|[0-9]*\\.?[0-9]+)([eE][-+]?[0-9]+)? - Matiaan

8

你的正则表达式只匹配数字字符。如果想要匹配小数点,你需要使用以下表达式:

Pattern.compile("\\d+\\.\\d+")

"."被转义是因为未转义时会匹配任何字符。
注意:这将只匹配具有小数点的数字,就像您示例中的一样。

2
如果您需要验证带有小数点、逗号、正数和负数的数字:
Object testObject = "-1.5";
boolean isDecimal = Pattern.matches("^[\\+\\-]{0,1}[0-9]+[\\.\\,][0-9]+$", (CharSequence) testObject);

祝你好运。


1
{1}不是隐式的吗? - Cutter
1
@cutter 是啊,我不记得为什么要添加那个 {1}。可能是为了更清晰或者因为我在2015年对正则表达式太菜了 xD。 - august0490
1
唯一一个正确处理负数(以及前导+的正数)的答案。 - Robert

2

如果想匹配任何数字和点的序列,可以将正则表达式更改为:

"(?<=C=)[.\\d]+"

如果您想确保只有一个点,请尝试以下方法:

"(?<=C=)\\d+(?:\\.\\d+)?"

您还需要注意,此模式可以匹配ABC=1.2.3;中的1.2。您应该考虑是否需要改进正则表达式以正确处理此情况。


0
如果您想要一个正则表达式,用于匹配可能是双精度或整数的输入,而不带有任何*.0的内容,您可以使用以下代码:
Pattern.compile("(-?\d+\.?\d*)")

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接