正则表达式解析国际浮点数

时间:2009-08-18 17:23:34

标签: regex internationalization

我需要一个正则表达式来获取可以

的数值
111.111,11

111,111.11

111,111

并分隔整数和小数部分,以便我可以使用正确的语法

存储在DB中

我试过([0-9]{1,3}[,.]?)+([,.][0-9]{2})?没有成功,因为它没有检测到第二部分:(

结果如下:

111.111,11 -> $1 = 111111; $2 = 11

5 个答案:

答案 0 :(得分:9)

第一回答:

匹配#,###,##0.00

^[+-]?[0-9]{1,3}(?:\,?[0-9]{3})*(?:\.[0-9]{2})?$

这匹配#.###.##0,00

^[+-]?[0-9]{1,3}(?:\.?[0-9]{3})*(?:\,[0-9]{2})?$

加入两者(有更聪明/更短的方式来编写它,但它有效):

(?:^[+-]?[0-9]{1,3}(?:\,?[0-9]{3})*(?:\.[0-9]{2})?$)
|(?:^[+-]?[0-9]{1,3}(?:\.?[0-9]{3})*(?:\,[0-9]{2})?$)

您还可以将捕获组添加到最后一个逗号(或点)以检查使用了哪一个。


第二回答:

正如 Alan M 指出的那样,我以前的解决方案可能无法拒绝像11,111111.00这样的值,其中缺少逗号,但另一个不是。经过一些测试后,我达到了以下正则表达式,避免了这个问题:

^[+-]?[0-9]{1,3}
(?:(?<comma>\,?)[0-9]{3})?
(?:\k<comma>[0-9]{3})*
(?:\.[0-9]{2})?$

值得一些解释:

  • ^[+-]?[0-9]{1,3}匹配第一个(1到3)数字;

  • (?:(?<comma>\,?)[0-9]{3})?匹配可选逗号,后跟更多3位数字,并在名为“逗号”的组中捕获逗号(或不存在的逗号);

  • (?:\k<comma>[0-9]{3})*匹配之前使用的逗号的零到任何重复(如果有),后跟3位数字;

  • (?:\.[0-9]{2})?$匹配字符串末尾的可选“美分”。

当然,这只会涵盖#,###,##0.00(不是#.###.##0,00),但您可以像上面一样加入正则表达式。


最终答案:

现在,一个完整的解决方案。缩进和换行只是为了可读性。

^[+-]?[0-9]{1,3}
(?:
    (?:\,[0-9]{3})*
    (?:.[0-9]{2})?
|
    (?:\.[0-9]{3})*
    (?:\,[0-9]{2})?
|
    [0-9]*
    (?:[\.\,][0-9]{2})?
)$

此变体捕获使用的分隔符:

^[+-]?[0-9]{1,3}
(?:
    (?:(?<thousand>\,)[0-9]{3})*
    (?:(?<decimal>\.)[0-9]{2})?
|
    (?:(?<thousand>\.)[0-9]{3})*
    (?:(?<decimal>\,)[0-9]{2})?
|
    [0-9]*
    (?:(?<decimal>[\.\,])[0-9]{2})?
)$

编辑1 :“美分”现在是可选的; 编辑2 :添加了文字; 编辑3 :添加第二个解决方案; 编辑4 :添加完整解决方案; 编辑5 :标题已添加; 编辑6 :捕获添加; 编辑7 :最后一个答案分为两个版本;

答案 1 :(得分:3)

我首先会使用这个正则表达式来确定逗号或点是否用作逗号分隔符(它取两个中的最后一个):

[0-9,\.]*([,\.])[0-9]*
然后我会剥去所有其他符号(之前的符号不匹配)。如果没有匹配项,则您已经有一个整数,可以跳过后续步骤。使用正则表达式可以轻松删除所选符号,但还有许多其他功能可以更快/更好地完成此操作。

然后你会得到一个整数形式的数字,后面跟一个逗号或一个点,然后是小数,其中整数和小数部分很容易用以下的正则表达式相互分开。

([0-9]+)[,\.]?([0-9]*)
祝你好运!

修改

这是python中的一个例子,我假设代码应该是自我解释的,如果不是,请问。

import re

input = str(raw_input())
delimiterRegex = re.compile('[0-9,\.]*([,\.])[0-9]*')
splitRegex = re.compile('([0-9]+)[,\.]?([0-9]*)')

delimiter = re.findall(delimiterRegex, input)

if (delimiter[0] == ','):
    input = re.sub('[\.]*','', input)
elif (delimiter[0] == '.'):
    input = re.sub('[,]*','', input)

print input

使用此代码,以下输入提供:

  • 111.111,11

    111111,11

  • <强> 111,111.11

    111111.11

  • 111,111

    111111

完成此步骤后,现在可以轻松修改字符串以满足您的需求。

答案 2 :(得分:1)

怎么样

/(\d{1,3}(?:,\d{3})*)(\.\d{2})?/

如果你关心验证逗号分别准确地分隔每3个数字, 或

/(\d[\d,]*)(\.\d{2})?/

如果你不这样做。

答案 3 :(得分:0)

如果我正确地解释你的问题,那么你说结果应该看起来像你说的“会”看起来像,那么我认为你只需要将逗号留在字符类中,因为它是用作分隔符而不是要匹配的部分。

所以摆脱“。”首先,然后匹配这两个部分。

$value = "111,111.11";
$value =~ s/\.//g;
$value =~ m/(\d+)(?:,(\d+))?/;

$ 1 =删除了句点的前导整数 $ 2 =如果不存在则为undef,如果存在,则为逗号后数字。

答案 4 :(得分:0)

参见Perl的Regexp::Common::number