Regex читает справа налево

Я искал короткий код, который может помещать запятые в набор чисел, пока я не перейду на этот сайт.

Код:

function addCommas(nStr)
{
    nStr += '';
    x = nStr.split('.');
    x1 = x[0];
    x2 = x.length > 1 ? '.' + x[1] : '';
    var rgx = /(\d+)(\d{3})/;
    while (rgx.test(x1)) {
        x1 = x1.replace(rgx, '$1' + ',' + '$2');
    }
    return x1 + x2;
}  

Прекрасно работает. Имея этот пример набор чисел:

addCommas('83475934.89');  

Вернет "83,475,934.89", но когда я прочитаю код, я ожидаю, что он вернет 8,3,4,7,5,934.89, но на этих сайтах объясняется, что

\d+ в сочетании с \d{3} будет соответствовать группе из трех чисел, которым предшествует любое количество чисел. Это приводит к тому, что поиск заменяется справа налево.

И я так запутался. Как этот код читается справа налево? Кроме того, что означает $1 и $2?

Ответ 1

Он соответствует справа налево, потому что он использует жадный шаблон, соответствующий. Это означает, что он сначала находит все цифры (\ d +), , затем пытается найти \d {3}. Например, в номере 2421567.56 он сначала будет соответствовать цифрам до ".". - 2431567 - затем работает назад, чтобы сопоставить следующие 3 цифры (567) в следующей части регулярного выражения. Он делает это в цикле, добавляя запятую между переменными $1 и $2.

$представляют собой сопоставляющие группы, сформированные в регулярном выражении с круглыми скобками, например. (\ d +) = $1 и (\ d {3}) = $2. Таким образом, он может легко добавлять символы между ними.

В следующей итерации жадное совпадение останавливается вместо вновь созданной запятой и продолжается до тех пор, пока оно не будет соответствовать > 3 цифрам.

Ответ 2

На самом деле это не чтение справа налево. Что действительно происходит, так это то, что он многократно применяет шаблон (\d+)(\d{3}) (через цикл while) и заменяет, пока он больше не будет соответствовать шаблону. Другими словами:

Итерация 1:

x1 = 83475934.89
x1.replace((\d+)(\d{3}), '$1' + ',' + '$2');
x1 = 83475,934.89

Итерация 2:

x1 = 83475,934.89
x1.replace((\d+)(\d{3}), '$1' + ',' + '$2');
x1 = 83,475,934.89

Итерация 3:

x1 = 83,475,934.89
x1.replace((\d+)(\d{3}), '$1' + ',' + '$2');
// no match; end loop

Edit:

Плюс, что означают $1 и $2?

Это ссылки на соответствующие группы (\d+) и (\d{3}) соответственно.

Здесь отличная ссылка для изучения того, как работают обычные выражения:
http://www.regular-expressions.info/quickstart.html

Ответ 3

Это объяснение было ниже на той же странице

Объяснение кода: код начинается с деления строки на две (nStr и nStrEnd), если есть десятичное число. Регулярное выражение используется для nStr для добавления запятых. Затем добавляется nStrEnd. Если строка не имела nStrEnd временно удалена, затем регулярная выражение будет форматировать 10.0004 как 10.0,004

Пояснение о регулярном выражении: \d + в сочетании с \d {3} будет соответствуют группе из трех чисел, которым предшествует любое количество чисел. Эта трюки поиска в замену справа налево.

$1 и $2 - это захваченные групповые совпадения из регулярного выражения. Вы можете прочитать больше на эту тему в Учебное пособие по регулярному выражению.

Ответ 4

Код читается справа налево, и он выполняет поиск самой большой строки цифр (\d+), за которой следуют 3 цифры (\d{3}). $1 и $2 - это соответственно самая большая строка цифр и 3 цифры. Поэтому он помещает запятую между ними, повторяя этот процесс, и может разбирать ее таким образом.

Ответ 5

Я написал регулярное выражение, которое делает одно и то же за один проход:

/(?!\b)(\d{3}(?=(\d{3})*\b))/g

Попробуйте это, например, с разными номерами в начале:

var num = '1234567890123456';

for(var i = 1; i <= num.length; i++)
{
  console.log(num.slice(0, -i).replace(/(?!\b)(\d{3}(?=(\d{3})*\b))/g, ',$1'));
}