首页 > 解决方案 > 正则表达式货币 Python 3.5

问题描述

我正在尝试在文本数据中重新格式化欧元。原始格式是这样的:EUR 3.000.00 或 EUR 33.540.000.- 。
我想将格式标准化为 3000.00 欧元或 33540000.00 欧元。
我已重新格式化 2.500 欧元。- 使用此代码成功:

import re
format1 = "a piece of text with currency EUR 2.500.- and some other information"
regexObj = re.compile(r'EUR\s*\d{1,3}[.](\d{3}[.]-)')
text1 = regexObj.sub(lambda m:"\u20ac"+"{:0.2f}".format(float(re.compile('\d+(.\d+)?(\.\d+)?').search(m.group().replace('.','')).group())),format1)
Out: "a piece of text with currency €2500.00 and some other information"

这给了我 2500.00 欧元,这是正确的。我尝试将相同的逻辑应用于其他格式无济于事。

format2 = "another piece of text EUR 3.000.00 and EUR 5.000.00. New sentence"
regexObj = re.compile('\d{1,3}[.](\d{3}[.])(\d{2})?')
text2 = regexObj.sub(lambda m:"\u20ac"+"{:0.2f}".format(float(re.compile('\d+(.\d+)?(\.\d+)?').search(m.group().replace('.','')).group())),format2)
Out: "another piece of text EUR €300000.00 and EUR €500000.00. New sentence"

format3 = "another piece of text EUR 33.540.000.- and more text"
regexObj = regexObj = re.compile(r'EUR\s*\d{1,3}[.](\d{3}[.])(\d{3}[.])(\d{3}[.]-)')
text3 = regexObj.sub(lambda m:"\u20ac"+"{:0.2f}".format(float(re.compile('\d+(.\d+)?(.\d+)?').search(m.group().replace('.','')).group())),format3)
Out: "another piece of text EUR 33.540.000.- and more text"

我认为问题可能出在 regexObj.sub() 上,因为它的 .format() 部分让我感到困惑。我试图在其中更改 re.compile('\d+(.\d+)?(.\d+)?') ,但我似乎无法生成我想要的结果。任何想法都非常感谢。谢谢!

标签: regexpython-3.xcurrency

解决方案


让我们从正则表达式开始。我的提议是:

EUR\s*(?:(\d{1,3}(?:\.\d{3})*)\.-|(\d{1,3}(?:\.\d{3})*)(\.\d{2}))

细节:

  • EUR\s*- 开始部分。
  • (?:- 非捕获组的开始 - 替代品的容器。
  • (- 捕获组 #1 的开始(带“.-”的整数部分,而不是小数部分)。
  • \d{1,3}- 最多 3 位数字。
  • (?:\.\d{3})*- ".ddd" 部分,0 次或更多次。
  • )- 第 1 组结束。
  • \.-- “。-“ 结尾。
  • |- 替代分隔符。
  • (- 捕获组 #2 的开始(整数部分)
  • \d{1,3}(?:\.\d{3})*- 就像在备选方案 1 中一样。
  • )- 第 2 组结束。
  • (\.\d{2})- 捕获组#3(点和小数部分)。
  • )- 非捕获组的结束。

我没有使用 lambda 函数,而是使用“普通”复制函数,我称之为repl. 它包含 2 个部分,用于第 1 组和第 2 + 3 组。

在这两种变体中,整数部分的点都被删除,但“最后”点(在整数部分之后)是第 3 组的一部分,因此不会被删除。

所以整个脚本如下所示:

import re

def repl(m):
    g1 = m.group(1)
    if g1:   # Alternative 1: ".-" instead of decimal part
        res = g1.replace('.','') + '.00'
    else:    # Alternative 2: integet part (group 2) + decimal part (group 3)
        res = m.group(2).replace('.','') + m.group(3)
    return "\u20ac" + res

# Source string
src = 'xxx EUR 33.540.000.- yyyy EUR 3.000.00 zzzz EUR 5.210.15 vvvv'
# Regex
pat = re.compile(r'EUR\s*(?:(\d{1,3}(?:\.\d{3})*)\.-|(\d{1,3}(?:\.\d{3})*)(\.\d{2}))')
# Replace
result = pat.sub(repl, src)

结果是:

xxx €33540000.00 yyyy €3000.00 zzzz €5210.15 vvvv

如您所见,无需使用floator format


推荐阅读