如何使用 JS 正则表达式查找所有不匹配字符的索引?

How to find indexes of all non-matching characters with a JS regex?

我有一个字符串,我想获取一个数组,其中包含该字符串中不符合特定正则表达式条件的字符的索引(位置)。

这里的问题是,如果我这样写:

let match;
let reg = /[A-Za-z]|[0-9]/g;
let str = "1111-253-asdasdas";
let indexes = [];

do {
    match = reg.exec(str);
    if (match) indexes.push(match.index);
} while (match);

有效。它 returns 所有数字或字母字符的索引。但问题是,如果我尝试做相反的事情,在 Regex 中使用负前瞻,就像这样:

let match;
let reg = /(?!([A-Za-z]|[0-9]))/g;
let str = "1111-253-asdasdas";
let indexes = [];

do {
    match = reg.exec(str);
    if (match) indexes.push(match.index);
} while (match);

它以无限循环结束。

我想要实现的结果与第一种情况相同,但使用负正则表达式,因此在这种情况下结果将是:

indexes = [4, 8]; // which are the indexes in which a non-alphanumerical character appears

是循环错了,还是正则表达式把事情搞砸了?也许 exec 不适用于负前瞻正则表达式?

我会理解正则表达式没有按我的预期工作(因为它可能格式错误),但我不理解无限循环,这让我认为 exec 可能不是实现我正在寻找的最好方法。

此方法将所有匹配字符替换为星号 *。然后,我们迭代替换的字符串并检索所有 not 匹配正则表达式字符 class.

的索引

var str = "1111-253-asdasdas";
var pattern = /[^A-Za-z0-9]/g;
str = str.replace(pattern, "*");

var indices = [];
for(var i=0; i < str.length;i++) {
    if (str[i] === "*") indices.push(i);
}
console.log(indices.toString());

在这种情况下,只有位置 4 和 8 的字符不匹配,因为它们是下划线。

原因

无限循环很容易解释:正则表达式有一个 g 修饰符,因此尝试匹配多次出现的模式,在上一次成功匹配结束后开始每次匹配尝试,也就是说,在lastIndex 值:

exec documentation:

If your regular expression uses the "g" flag, you can use the exec() method multiple times to find successive matches in the same string. When you do so, the search starts at the substring of str specified by the regular expression's lastIndex property

但是,由于您的模式匹配空字符串,并且您不检查索引是否等于 lastIndex 的条件,因此正则表达式无法在字符串中前进。

解决方案

使用正则表达式匹配任何非字母数字字符,/[\W_]/g。由于它不匹配空字符串,RegExp 对象的 lastIndex 属性 将随着每次匹配而改变,并且不会发生无限循环。

JS 演示:

let match, indexes = [];
let reg = /[\W_]/g;
let str = "1111-253-asdasdas";

while (match = reg.exec(str)) {
    indexes.push(match.index);
}
console.log(indexes);

另请参阅