如何从字符串中提取数字?

5
我正在使用Java StreamTokenizer来提取字符串中的各种单词和数字,但是遇到了一个问题,涉及包含逗号的数字,例如10,567被读作10.0和,567。
我还需要从可能出现的数字中删除所有非数字字符,例如$678.00应该是678.00或-87应该是87。
我相信这可以通过whiteSpace和wordChars方法实现,但有没有人知道如何做?
目前基本的streamTokenizer代码如下:
        BufferedReader br = new BufferedReader(new StringReader(text));
        StreamTokenizer st = new StreamTokenizer(br);
        st.parseNumbers();
        st.wordChars(44, 46); // ASCII comma, - , dot.
        st.wordChars(48, 57); // ASCII 0 - 9.
        st.wordChars(65, 90); // ASCII upper case A - Z.
        st.wordChars(97, 122); // ASCII lower case a - z.
        while (st.nextToken() != StreamTokenizer.TT_EOF) {
            if (st.ttype == StreamTokenizer.TT_WORD) {                    
                System.out.println("String: " + st.sval);
            }
            else if (st.ttype == StreamTokenizer.TT_NUMBER) {
                System.out.println("Number: " + st.nval);
            }
        }
        br.close(); 

还有人能建议一个正则表达式来实现这个吗?我不确定在这里使用正则表达式是否有用,因为任何分析都将在从字符串读取令牌之后进行。

谢谢

Morgan先生。


1,2,3,4 应该发生什么? - polygenelubricants
5个回答

9

StreamTokenizer已经过时,更好的选择是使用Scanner,以下是解决您问题的示例代码:

    String s = "$23.24 word -123";
    Scanner fi = new Scanner(s);
    //anything other than alphanumberic characters, 
    //comma, dot or negative sign is skipped
    fi.useDelimiter("[^\\p{Alnum},\\.-]"); 
    while (true) {
        if (fi.hasNextInt())
            System.out.println("Int: " + fi.nextInt());
        else if (fi.hasNextDouble())
            System.out.println("Double: " + fi.nextDouble());
        else if (fi.hasNext())
            System.out.println("word: " + fi.next());
        else
            break;
    }

如果您想使用逗号作为浮点数分隔符,请使用fi.useLocale(Locale.FRANCE);

这非常有帮助。我已经添加了一些其他字符。非常感谢。 - Mr Morgan

5

试试这个:

String sanitizedText = text.replaceAll("[^\\w\\s\\.]", "");

SanitizedText 只包含字母数字和空格;之后对其进行分词应该很容易。

编辑

修改以保留括号末尾的小数点。 . 对正则表达式来说是“特殊”的字符,因此需要使用反斜杠转义。


1
很容易。只需在括号内添加任何其他你想保留的字符。我会为你修复它... - Carl Smotricz
当然可以,在括号末尾添加一个“-”。但是,这样可能会遇到负数。不过,你可以通过简单的“if”测试来解决这些问题。 - Carl Smotricz
我已经编写好了代码并可以测试负数。但是如果姓名中有撇号,比如 O'Finnegan,该怎么办? - Mr Morgan
这是一个不正确的解决方案。它无法正确处理货币中的小数或千位分隔符。正如@tulskiy建议的那样,Scanner是JavaSE库中正确且更简单的解决方案。 - Alain O'Dea
2
我向@tulskiy脱帽致敬,他的解决方案比我的容易本地化得多。我为他更好的解决方案点赞。 - Carl Smotricz
显示剩余3条评论

4
这对我有用:
String onlyNumericText = text.replaceAll("\\\D", "");

编辑后多了一个\。应该是\D。 - Michael Chatiskatzi

1
    String str = "1,222";
    StringBuffer sb = new StringBuffer();
    for(int i=0; i<str.length(); i++)
    {
        if(Character.isDigit(str.charAt(i)))
            sb.append(str.charAt(i));
    }
    return sb.toString()

0

可以使用正则表达式来完成这个任务:

s/[^\d\.]//g

请注意,它会吞掉所有逗号,这可能是您使用美国数字格式时想要的,其中逗号仅用于分隔千位数。在某些语言中,逗号被用作小数点分隔符。因此,在解析国际数据时要小心。

我把这留给你来将其翻译成Java。


这就是为什么我想保留逗号的原因。 - Mr Morgan
我以为你需要数字而不是它的字符串表示。没关系。 - gorn

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