javascript - внутренний индекс regexp exec не выполняется, если первый символ не совпадает

Мне нужно сопоставить номера, которым не предшествует "/" в группе.

Для этого я сделал следующее регулярное выражение:

var reg = /(^|[^,\/])([0-9]*\.?[0-9]*)/g;

Первая часть соответствует началу строки и чему-либо еще, кроме "/", вторая часть соответствует числу. Все работает нормально относительно регулярного выражения (это соответствует тому, что мне нужно). Я использую https://regex101.com/ для тестирования. Пример здесь: https://regex101.com/r/7UwEUn/1

Проблема в том, что когда я использую его в js (скрипт ниже), он входит в бесконечный цикл, если первый символ строки не является числом. При ближайшем рассмотрении кажется, что он совпадает с началом строки и никогда не продвигается дальше.

 var reg = /(^|[^,\/])([0-9]*\.?[0-9]*)/g;
 var text = "a 1 b";
 while (match = reg.exec(text)) {
     if (typeof match[2] != 'undefined' && match[2] != '') {
         numbers.push({'index': match.index + match[1].length, 'value': match[2]});
     }
 }

Если строка начинается с цифры ("1 a b"), все в порядке.

Проблема, кажется, здесь (^|[^,/]) - удаление ^ | исправит проблему с бесконечным циклом, но он не будет соответствовать тому, что мне нужно в строках, начинающихся с чисел.

Есть идеи, почему внутренний индекс не прогрессирует?

1 ответ

Решение

Бесконечный цикл вызван тем фактом, что ваше регулярное выражение может соответствовать пустой строке. Вам вряд ли понадобятся пустые строки (даже судя по вашему коду), поэтому сделайте так, чтобы оно совпадало хотя бы с одной цифрой, замените последнюю * с +:

var reg = /(^|[^,\/])([0-9]*\.?[0-9]+)/g; 
var text = "a 1 b a 2 ana 1/2 are mere (55";
var numbers=[];
while (match = reg.exec(text)) {
    numbers.push({'index': match.index + match[1].length, 'value': match[2]});
 }
console.log(numbers);

Обратите внимание, что это регулярное выражение не будет соответствовать числам, таким как 34. и в этом случае вы можете использовать /(^|[^,\/])([0-9]*\.?[0-9]+|[0-9]*\.)/g Посмотрите это демо регулярных выражений.

Кроме того, вы можете использовать другой "трюк", продвиньте регулярное выражение lastIndex вручную при отсутствии совпадений:

var reg = /(^|[^,\/])([0-9]*\.?[0-9]+)/g;
 var text = "a 1 b a 2 ana 1/2 are mere (55";
 var numbers=[];
 while (match = reg.exec(text)) {
    if (match.index === reg.lastIndex) {
        reg.lastIndex++;
    }
    if (match[2]) numbers.push({'index': match.index + match[1].length, 'value': match[2]});
 }
 console.log(numbers);

Другие вопросы по тегам