Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Регулярные выражения > разделение числа по разрядам


Автор: Evghenusi 21.9.2014, 21:50
Доброго времени суток.
Ребят, я знаю что тут водятся Гуру, поэтому к вам и заглянул  smile 

Регулярку для своего случая нашёл
Код

"1231231.23".replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,") // "1,231,231.23"


И всё бы хорошо, но хочется вникнуть, а не бездумно использовать чужие плоды.

Как я понимаю: 
находим цифру, дальше ?= вперёд смотрящее, получается что от цифры идём влево, но если верить поведению http://www.regexr.com/v1/ идём на три цифры влево с включительно ранее найденной, и дальше до бесконечности ищем по три цифры если после них символ не цифра..........бред какой-то написал.

Сжальтесь, объясните пожалуйста регулярку.

p.s. в Perl я ни бум бум, но знаю что там есть инструмент для просмотра выполнения регулярок, вот только он мне недоступен((

Автор: hobo1mts 22.9.2014, 06:16
Джеффри Фридл. Регулярные выражения. Третье издание.– СПб.: СимволПлюс, 2008. Со стр. 88 по 97 ОЧЕНЬ подробно разобран случай.

Автор: Evghenusi 22.9.2014, 09:14
спасибо, попробую найти)

Автор: Pfailed 22.9.2014, 10:41
Вот что выдаёт тот самый инструмент: http://jsfiddle.net/L7cbot1y/
Думаю, тут всё понятно

Автор: Evghenusi 22.9.2014, 11:27
hobo1mts, спасибо больше за рекомендуемую книгу, понравилась.

Правда видимо я невнимательно читал, потому что конец регулярки - (?!\d) остался не понятен.
К примеру возьмём число крупнее (хоть и нет разницы)   -    999999999999999999999999999999999999999999.23
Если я правильно понимаю проверка идёт слева на право, находим цифру, а дальше проверяем что бы справа от неё было по три цифры. И если я правильно понимаю, так доходим до конца строки, но ведь мы проверяем кроме трёх знаков ещё и что бы после них не было цифры в конце - (?!\d).

 smile 
Пойти перечитать?


Pfailed, спасибо) ооох, чёрт дёрнул меня за язык  smile 

Автор: Evghenusi 22.9.2014, 12:02
аааа, кажется понял.

берётся строка, находим первую цифру, дальше ищем по три цифры до конца строки, и именно что бы по три цифры, иначе нам не подходит, и проверка что бы конец строки был или не число, не суть важно. И так проверяем для каждой цифры, и если условие сходится ставим разделитель.
Получается для 999999999999999999999999999999999999999999.23 проделываются 42 итерации.

Я правильно понял?

Добавлено через 4 минуты и 16 секунд
я до этого ошибочно полагал что разделитель ставится за одну итерацию

Добавлено через 4 минуты и 49 секунд
разделители ставятся*

Автор: Pfailed 22.9.2014, 12:10
Работает так.
На входе 999999999999999999999999999999999999999999.23
Первое выражение в регулярке отсекает первую цифру - она матчится
Код

(9)99999999999999999999999999999999999999999.23

Дальше в действие вступает жадное выражение (\d{3})+ которое берёт по три цифры столько раз сколько может
Код

(9){999}{999}{999}{999}{999}{999}{999}{999}{999}{999}{999}{999}{999}99.23
                                                                    ^
                                            тут выражение заматчить три цифры уже не может
                                                      поэтому останавливается

Дальше ищем совпадение на (?!\d). Т.е за последней захваченной 9 должна быть не цифра. А у нас там
Код

99.23

Т.е. весь матчинг на данном этапе оканчивается неудачно. Значит запятую после первой 9 выражение не поставит

Так как у на указан модификатор /g то далее сдвинувшись на одну цифру вправо всё повторится
Т.е теперь это
Код

9(9)9999999999999999999999999999999999999999.23

Очевидно, что на этом этапе всё снова окончится неудачно.
И лишь на следующем
Код

99(9){999}{999}{999}{999}{999}{999}{999}{999}{999}{999}{999}{999}{999}.23

Взяли по три цифры столько раз сколько смогли. А дальше должна быть не цифра. А там действительно не цифра. Наконец то поиск закончился успешно!
А значит после 3-й девятки сначала будет поставлена запятая. Далее вся история повторяется ещё много раз пока не будет достигнут конец строки.

Собственно это краткий пересказ того, что выдаёт тот самый инструмент.

Автор: Evghenusi 22.9.2014, 12:13
Pfailed, спасибо за объяснение, моя последняя теория оправдалась)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)