regex - 正则表达式货币 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+)?') ,但我似乎无法生成我想要的结果。任何想法都非常感谢。谢谢!
解决方案
让我们从正则表达式开始。我的提议是:
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
如您所见,无需使用float
or format
。
推荐阅读
- regex - 过滤 UniProt dat.-file 中的氨基酸序列
- android - 如何画2/5的圆
- javascript - 针对另一个对象数组循环遍历对象数组
- javascript - reactjs中如何引用html块的一部分
- javascript - 即使对象已正确实例化,JSONObject 也无法从现有对象中读取属性
- java - 有没有一种新方法可以将 java 8 中相同列表的元素与 lambda 进行比较?
- java - 使用循环将字符串数组插入 JTree 嵌套节点
- android - 卸载应用程序时 SQLite 不会擦除
- sql - Power Designer 16.6 不会为主列创建 AUTO_INCREMENT
- r - 如何在 R 中获得符合要求的组合