Мобильная
версия

Немного о регулярных выражениях

Дата: Категория: Регулярные выражения

Данную заметку меня сподвигло написать мое воспоминание о старом добром регулярном выражении которое упоминается в моей статье

Кстати вот оно

price.replace(/(\d)(?=(\d\d\d)+([^\d]|$))/g, '$1 ')

Что же оно делает?

Оно разбивает число по разрядам например
на выходе есть число 10000000, а после обработки его этой регуляркой мы получаем 10 000 000

А теперь разберем по частям как и что именно тут происходит.

(\d)(?=(\d\d\d)+([^\d]|$))
Можно разбить на несколько частей - пойдем с конца.
([^\d]|$)

Эта часть означает либо любой символ кроме числа ([^\d]) либо конец строки ($)
Хорошо, то есть это у нас отметка конца числа - например если в эту регулярку передать строку "12345NUMBER", то работать она будет только с первым числом (тоже самое если перед передачей строки в регулярку мы обработаем его функцией parseInt)
Что у нас идет в скобочках дальше?

(\d\d\d)+
На самом деле более правильная запись этой части регулярки была бы (\d{3})+, но не будем придираться ;)
тут у нас идет 3 числа повторяющихся 1 и более раз.
Вот мы уже приближаемся к разгадке сути этого выражения.

У нас есть 3 числа которые должны повториться 1 и более раз и после них сразу конец строки (пока выбросим любой не цифровой символ), и получается что в следующих числах она обработает выделенные части

  • 10 - не применяется, так как цифр меньше 3х
  • 100 - применяется на все число, (3 цифры повторяющиеся 1 и более раз)
  • 1000 - последние 3 нуля попадают под нашу регулярку
  • 10000000 - под регулярку попадают последние 6 нулей.

Еще ближе к разгадке - на примере сверху в последних 2х пунтках мы явно видим разряды у выделенных чисел.

Теперь перейдем к началу нашего выражения

(\d)
наличие числа.
(к неведомым символам ?= я вернусь чуть позже)
Если пересмотреть примеры выше то нашему выражению соответствуют только последние 2 числа.
Первое вообще не соответствует, а у второго перед 3-мя символами нет числа.

Пока все просто - но есть небольшая несостыковочка. По логике того что я описал выше если применить полное выражение ( price.replace(/(\d)(?=(\d\d\d)+([^\d]|$))/g, '$1 ') ) к числу, например, 1000 то получаем все верно - 
Число (1 - $1), и после него 3 числа в количестве один и более (000 - $2) и заменяем все это на '$1 ' 
то в итоге получим строку "1 ".
Как-то не хорошо получается.

Но я еще не все рассказал про данное выражение, и как и обещал возвращаюсь к неведомым символам ?=

Что они означают?
Такая конструкция называется "Позитивный просмотр вперед" (подробнее о просмотрах можно почитать в википедии)

А означает она то что в скобках в начале которых стоит ?= только проверяется на соответствие, но не учитывается при разборе.
Если более простым языком то мы проверяем чтобы после первой цифры (самое начало регулярного выражения - (\d)) было 3 символа в количестве 1 и более, но ничего с ними не делает, и после того как применил регулярное выражение к 1 части начинает применять его ко второй, и так пока строка не закончится.

Я если честно немного сам запутался в таком объяснении ;)

Чтож, думаю что пример как работает это выражение расписанный по шагам уберет все вопросы.
Возьмем число 10 миллионов - 10000000
(в каждой итерации я буду выделять красным ту часть числа с которой выражение работает, а зеленой - часть которую оно уже обработало)

  1. 10000000
    Идем с конца, до тех пор пока количество символов будет меньше 3 но больше 1
    10 (\d) - 000 (\d\d\d) - 000 (\d\d\d)
    Осталось у нас на руках - 10 (так как в регуярке вначале стоит всего 1 цифра то поидее должен быть 0, но для наглядности я буду применять 10)
    для нашей 10 выражение выделило область памяти ($1) а все оставшееся выражение регуялрка только проверила на соответствие, но не учла - как будто еще не дошла до него.
    И получается что в числе 10000000 у нас образовалось 2 части - 10 (уже проверенное регуляркой - $1) и 000000 (про них наше выражение, скажем так, "забыло")
    И исходя из второй части ('$1 ') мы должны в нашем числе заменить "10" на "10 ", получив тем самым "10 000000"
  2. 10 000000
    На второй итерации наша регуярка работает только с шестью нулями.
    Опять идем с конца, пока количество символов будет меньше 3 но больше 1 
    Ничего нет000 (\d\d\d) - 000 (\d\d\d). Выражение не подходит, значит нужно делать так
    000 (\d) - 000 (\d\d\d). Так как последние 3 нуля только проверяются на наличие, то их тоже забываем, и получается что первые три нуля это $1
    Следовательно теперь нам нужно заменить в нашей строке "000" на "000 ", получив тем самым "10 000 000"
    То что нам нужно у нас уже есть, но как вы помните регулрка "забыла" последние 3 нуля, и ей еще предстоит их обработать
  3. 10 000 000
    На третьей итерации у нас осталось следующая строка - "000", но как вы уже поняли она не подходит под наше регулярное выражение, и оно просто пропускается.
  4. 10 000 000
    Регулярное выражение закончило свою работу и выдает нам результат - "10 000 000"

Вот именно так и получается что простое регулярное выражение может заменить алгоритм разбивки числа по разрядам.
Регулярные выражения очень мощный инструмент любого программиста - не пренебрегайте ими.
Надеюсь мои разъяснения что да как были не слишком сложны и не довели вас до белого коления, или не нагнали на вас сон.

Теги: #price format, #Регулярные выражения

Ваша оценка:

Рейтинг: 10.0 (Оценок: 2)

Комментарий:

Copyright © DOC_tr 2015-2017 г. Все права защищены
Яндекс.Метрика
Перейти к мобильной версии