Regex: преобразование сумм в валюте (из различных форматов) в действительное число с плавающей точкой - PullRequest
1 голос
/ 26 февраля 2020

Я работаю над парсером для счетов и нашел различные форматы валют. Вместо того, чтобы переопределять конкретный случай c для каждого счета-фактуры, я бы предпочел иметь общий шаблон, который работает для всех случаев, использующих замену Regex.

Примеры форматов ввода

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}))?/ со строкой замены $1$2.$4

Но это приводит к выводу

2578.20
2354.20
234.
234256.20
234205.
246548.
244056.
26155.25
.
1220.  <---- WRONG
1333.  <---- WRONG

Я могу жить с точкой в ​​конце, как это работает для floatval () в PHP и возможно, и другие языки. Но последние два случая недействительны. Я знаю, что он соответствует первому (\d{0,3}) вместо (\d{0,2}) паттерна в конце. Но я не знаю, как это исправить ...

Ответы [ 2 ]

3 голосов
/ 26 февраля 2020

Вы можете использовать чередование с 2 группами захвата и preg_replace_callback

Совпадение с любым символом, кроме ди git, точки или запятой, или совпадение с точкой или запятой, когда справа не являются 2 цифрами в конце строки и заменяют пустую строку.

В противном случае запишите запятую и замените ее точкой.

([^\d.,]|[.,](?!\d{2}$))|(,)

Regex demo | Php демо

Например

$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
1 голос
/ 26 февраля 2020

Вы можете использовать [^\d\n](?!\d\d$)

Объяснение:

[^\d\n] - класс отрицательных символов - соответствует любому символу, кроме di git или символу новой строки

( ?! ...) `- отрицательный взгляд вперед - совпадение, если шаблон внутри НЕ сопоставлен перед этой позицией

\d\d$ - сопоставить две цифры и конец строки

Демо

Удаляет все не-ди git символы и оставляет только тогда, когда они появляются в конце строки вместе с двумя цифрами, то есть они являются десятичной частью:)

Заменить сопоставленный текст пустой строкой.

...