数字格式的正则表达式

时间:2015-07-06 10:28:03

标签: regex

您能否建议一个支持美国和欧洲数字格式的正则表达式

例如:US - 999,999.99     英国 - 999.999,99

3 个答案:

答案 0 :(得分:0)

一个简单的解决方案是匹配一个或另一个:

(?:\d{1,3})(?:\.\d{3})?(?:\.\d{3})?(?:,\d+)?|(?:\d{1,3})(?:,\d{3})?(?:,\d{3})?(?:\.\d+)?

匹配1-3位数字,可选地后跟完整停止和三位数字,可选地后跟全停和三位数字,可选地后跟一个逗号和任意数量的数字(根据您的示例,您可能希望限制为两位) 。然后,如果这不匹配,请尝试完全停止并以逗号反转。

编辑: 考虑到你在kbysiec的回答中的评论,你可能想检查开始和结束 -

(?:\s|^)(?:(?:\d{1,3})(?:\.\d{3})?(?:\.\d{3})?(?:,\d+)?|(?:\d{1,3})(?:,\d{3})?(?:,\d{3})?(?:\.\d+)?)(?:\s|$)

这可以确保数字前面有空格或行的开头,并以空格或行尾结束。

此致

编辑2:

(?:\s|^)(?:(?:\d{1,3})(?:\.\d{3})*(?:,\d+)?|(?:\d{1,3})(?:,\d{3})*(?:\.\d+)?)(?:\s|$)

缩短并允许数字为任意长度。

答案 1 :(得分:0)

(?<=\s|^)(?:\d{1,3}(?:,\d{3})*(?:\.\d+)?|\d{1,3}(?:.\d{3})*(?:\,\d+)?)(?=\s|$)应该正确匹配所有内容,同时检查点/逗号的错误展示位置,如here

所示

在最后一个前瞻之前投掷|\d*([,.]\d+)?以匹配非分开的数字。

这个想法是你会有,xxx.yy,在这种情况下,有一个长度为1-3的数字。这种情况可以重演。

尽管如此,这对于正则表达式来说并不是一件容易的事,而且这个正则表达式不是很易读。其他一些工具可能会更好。

答案 2 :(得分:0)

首先,每当有人要求正则表达式时,我的第一反应就是询问这是否适合这项工作:https://softwareengineering.stackexchange.com/q/223634/98845

有些语言提供了获取货币价值的方法。这个答案将使用C ++的:get_money

这样的输入:

  

Jonathan Mee $ 1,234.56 987654321 true

可以在流:get_money中使用cin >> a >> b >> get_money(c) >> d >> e; 来分配值:

  • string a"Jonathan"
  • string b"Mee"
  • long double c123456
  • int d987654321
  • bool etrue

get_money的处理方式基于流locale,特别是locale的{​​{3}}。可能已经有locale的编译器/操作系统支持已经以这种方式处理资金:moneypunct

如果没有内置支持,请不要担心。 locale的方面是支持广泛自定义的C ++功能,要解决此问题,只需要覆盖https://msdn.microsoft.com/en-us/goglobal/bb896001.aspxdo_decimal_point。这里有一个关于如何执行此操作的详尽说明:do_thousands_sep但是就本答案而言,该答案的punct_facet将被批评为ganked:

template <typename T>
class punct_facet : public T {
private:
    void Init(const T* money){
        const auto vTablePtrSize = sizeof(void*);

        memcpy(reinterpret_cast<char*>(this) + vTablePtrSize, reinterpret_cast<const char*>(money) + vTablePtrSize, sizeof(T) - vTablePtrSize);
    }
protected:
    typename T::char_type do_decimal_point() const {
        return typename T::char_type(',');
    }

    typename T::char_type do_thousands_sep() const {
        return typename T::char_type('.');
    }
public:
    punct_facet(){
        Init(&use_facet<T>(cout.getloc()));
    }

    punct_facet(const T* money){
        Init(money);
    }
};

这样的实现允许像这样使用https://stackoverflow.com/a/31390558/2642059

locale foo("en-US");

cin.imdue(locale(foo, new punct_facet<moneypunct<char>>(&use_facet<moneypunct<char>>(foo))));

这意味着输入如下:

  

Jonathan Mee $ 1.234,56 987654321 true

可以使用原始命令cin >> a >> b >> get_money(c) >> d >> e;读取,以分配值:

  • string a"Jonathan"
  • string b"Mee"
  • long double c123456
  • int d987654321
  • bool etrue

即使是未经训练的人也可以看到punct_facet类比一次设置和使用正则表达式所需的代码更多。 C ++的moneypunct在代码中优于regex,其中多次使用它的方式无法封装到单个regex函数中。与正则表达式相比,moneypunct也提供了明显的优势:

  1. 直接在流中使用
  2. 在输入错误处理方面具有更高的特异性
  3. 提供进一步的自定义,包括:负格式,正格式,货币符号等
  4. 与流出货币的locale facet constructor兼容
  5. 如果性能考虑因素适用,get_money会使用比正则表达式更专业的代码