正则表达式:将货币金额(从各种格式)转换为有效的浮点数
Regex: Converting currency amounts (from various formats) to a valid float
我正在开发发票解析器,我发现了各种不同的货币格式。与其为每张发票重新实现一个特定的案例,我宁愿有一个适用于所有案例的通用模式,使用正则表达式替换。
示例输入格式
2.578,20
2 354,20
234
234,256.20
234,205
246 548
244'056
26'155.25
12,20
13.33
期望输出
2578.20
2354.20
234
234256.20
234205
246548
244056
26155.25
12.20
13.33
我目前的进度
到目前为止,我已经设法创建了一些几乎可以工作的东西
/^(\d{0,3})?[\.\ ,']?(\d{0,3})([\.,](\d{0,2}))?/
替换字符串 .
但这会产生输出
2578.20
2354.20
234.
234256.20
234205.
246548.
244056.
26155.25
.
1220. <---- WRONG
1333. <---- WRONG
我可以接受在末尾有一个点,因为这适用于 PHP 中的 floatval(),可能也适用于其他语言。但后两种情况无效。我知道它匹配第一个 (\d{0,3})
而不是末尾的 (\d{0,2})
模式。但是我不知道如何解决这个问题...
你可以使用 [^\d\n](?!\d\d$)
解释:
[^\d\n]
- 否定字符 class - 匹配数字或换行符以外的任何字符
(?!...)` - 负前瞻 - 匹配,如果内部模式在该位置之前不匹配
\d\d$
- 匹配两个数字和字符串结尾
它会删除任何非数字字符,仅当它们与两位数字一起出现在字符串末尾时才保留,这意味着它们是小数部分:)
用空字符串替换匹配文本。
您可以交替使用 2 个捕获组和 preg_replace_callback
匹配除数字、点或逗号以外的任何字符,或者当右边不是字符串末尾的 2 位数字时匹配点或逗号并用空字符串替换。
否则捕获逗号并将其替换为点。
([^\d.,]|[.,](?!\d{2}$))|(,)
例如
$pattern = "~([^\d.,]|[.,](?!\d{2}$))|(,)~m";
$strings = [
"2.578,20",
"2 354,20",
"234",
"234,256.20",
"234,205",
"246 548",
"244'056",
"26'155.25",
"12,20",
"13.33",
];
foreach ($strings as $string) {
echo preg_replace_callback($pattern, function ($matches) {
if (isset($matches[2])) return ".";
if (isset($matches[1])) return "";
}, $string) . PHP_EOL;
}
输出
2578.20
2354.20
234
234256.20
234205
246548
244056
26155.25
12.20
13.33
我正在开发发票解析器,我发现了各种不同的货币格式。与其为每张发票重新实现一个特定的案例,我宁愿有一个适用于所有案例的通用模式,使用正则表达式替换。
示例输入格式
2.578,20
2 354,20
234
234,256.20
234,205
246 548
244'056
26'155.25
12,20
13.33
期望输出
2578.20
2354.20
234
234256.20
234205
246548
244056
26155.25
12.20
13.33
我目前的进度
到目前为止,我已经设法创建了一些几乎可以工作的东西
/^(\d{0,3})?[\.\ ,']?(\d{0,3})([\.,](\d{0,2}))?/
替换字符串 .
但这会产生输出
2578.20
2354.20
234.
234256.20
234205.
246548.
244056.
26155.25
.
1220. <---- WRONG
1333. <---- WRONG
我可以接受在末尾有一个点,因为这适用于 PHP 中的 floatval(),可能也适用于其他语言。但后两种情况无效。我知道它匹配第一个 (\d{0,3})
而不是末尾的 (\d{0,2})
模式。但是我不知道如何解决这个问题...
你可以使用 [^\d\n](?!\d\d$)
解释:
[^\d\n]
- 否定字符 class - 匹配数字或换行符以外的任何字符
(?!...)` - 负前瞻 - 匹配,如果内部模式在该位置之前不匹配
\d\d$
- 匹配两个数字和字符串结尾
它会删除任何非数字字符,仅当它们与两位数字一起出现在字符串末尾时才保留,这意味着它们是小数部分:)
用空字符串替换匹配文本。
您可以交替使用 2 个捕获组和 preg_replace_callback
匹配除数字、点或逗号以外的任何字符,或者当右边不是字符串末尾的 2 位数字时匹配点或逗号并用空字符串替换。
否则捕获逗号并将其替换为点。
([^\d.,]|[.,](?!\d{2}$))|(,)
例如
$pattern = "~([^\d.,]|[.,](?!\d{2}$))|(,)~m";
$strings = [
"2.578,20",
"2 354,20",
"234",
"234,256.20",
"234,205",
"246 548",
"244'056",
"26'155.25",
"12,20",
"13.33",
];
foreach ($strings as $string) {
echo preg_replace_callback($pattern, function ($matches) {
if (isset($matches[2])) return ".";
if (isset($matches[1])) return "";
}, $string) . PHP_EOL;
}
输出
2578.20
2354.20
234
234256.20
234205
246548
244056
26155.25
12.20
13.33