【问题标题】:Regex to parse international floating-point numbers正则表达式解析国际浮点数
【发布时间】:2010-11-20 16:29:36
【问题描述】:

我需要一个正则表达式来获取可以是的数值

111.111,11

111,111.11

111,111

并将整数和小数部分分开,以便我可以使用正确的语法存储在数据库中

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

结果应该是这样的:

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

【问题讨论】:

  • 只是出于好奇,你为什么会有这样的模式:11.111,111,即与实际值相反的 (111,111.11)
  • 只是为了证明这个白痴。这样用户就不必记住正确的模式是什么
  • 这其实很聪明,因为世界上有很多国家使用逗号作为小数分隔符。如需列表,请在此处查看:en.wikipedia.org/wiki/…
  • 你用 111,111 做什么还是不允许的?
  • 111,111 = 111111。所以它没有小数:)

标签: regex internationalization


【解决方案1】:

第一个答案:

这匹配#,###,##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)位数字;

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

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

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

当然,这只会涵盖#,###,##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:添加文字; edit 3:添加第二个解决方案; edit 4:添加了完整的解决方案; edit 5:添加了标题; edit 6:添加捕获; 编辑 7:最后一个答案分为两个版本;

【讨论】:

  • +1。我会将锚移到交替之外。您也可以将常见的前导和尾随元素移到它之外,但这并不一定值得在可读性上进行权衡
  • 可读性不是正则表达式的强项,但我同意。感谢您的投票:)
  • 刚刚注意到,千位分隔符应该不是可选的;例如,(?:\.?[0-9]{3})* 应该是 (?:\.[0-9]{3})*。否则,您可以匹配 11,111111.00 或 1111.111,00 之类的内容。
  • 好的,但是如果您希望它们是可选的呢?
  • 现在,它是可选的,没有您指出的问题。 :)
【解决方案2】:

请参阅 Perl 的 Regexp::Common::number。

【讨论】:

    【解决方案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

      111,111

    在这一步之后,现在可以轻松地修改字符串以满足您的需求。

    【讨论】:

    • 我很确定这个答案是错误的,但我不能肯定地说,因为你并没有真正说明你是如何使用正则表达式的(但这就是在那里投反对票的充分理由)。您能解释一下如何区分千位分隔符和小数分隔符(通过测试示例)吗?
    • 第一个正则表达式将通过找出最后出现的小数点来确定小数点分隔符是什么。然后,您剥离其他运营商的号码。你会留下一个没有千位分隔符的数字。其余的应该是小菜一碟。稍后将发布示例代码。
    • 根据 OP,111,111 中的逗号是千位分隔符 (TS)。如果存在小数分隔符 (DS),则必须紧跟两位数字(他在问题下的 cmets 中清除了这一点)。因此,您的第一个正则表达式必须像 OP 一样以 ([,.][0-9]{2})? 结尾。但他也在尝试验证 TS 是否正确分发。
    【解决方案4】:

    如果我正确解释了您的问题,以便您说结果应该看起来像您所说的“将”看起来,那么我认为您只需要将逗号从字符类中删除,因为它是用作分隔符,而不是要匹配的部分。

    所以去掉“。”首先,然后匹配两个部分。

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

    $1 = 去掉句点的前导整数 $2 = undef(如果不存在)或逗号后数字(如果存在)。

    【讨论】:

      【解决方案5】:

      怎么样

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

      如果您关心验证逗号是否准确分隔每 3 位数字, 或

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

      如果你不这样做。

      【讨论】:

      • 这不会验证他的第一个例子; 111.111,11
      • 是的。我没有注意到那个。对不起。
      猜你喜欢
      • 1970-01-01
      • 2012-09-20
      • 2011-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-30
      • 1970-01-01
      相关资源
      最近更新 更多