javascript - 如果第一个字符不匹配,regexp exec 内部索引不会进行

javascript - regexp exec internal index doesn't progress if first char is not a match

我需要匹配组中不以“/”开头的数字。

为了做到这一点,我制作了以下正则表达式:

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

第一部分匹配字符串的开头和除“/”以外的任何其他内容,第二部分匹配数字。关于正则表达式,一切正常(它符合我的需要)。我用 https://regex101.com/ for testing. Example here: 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") 开头,则一切正常。

问题似乎出在此处 (^|[^,/]) - 删除 ^|将解决无限循环的问题,但它与我需要的以数字开头的字符串不匹配。

知道为什么内部索引没有进展吗?

无限循环是由于您的正则表达式可以匹配空字符串造成的。你不太可能需要空字符串(即使根据你的代码判断),所以让它至少匹配一个数字,将最后一个 * 替换为 +:

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,请参阅 this regex demo

或者,您可以使用另一个 "trick",在不匹配时手动推进正则表达式 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);