4

我有一个字符串,我想获得一个数组,其中包含该字符串中与某个正则表达式条件不匹配的字符的索引(位置)。

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

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);

有用。它返回所有数字或字母字符的索引。但问题是,如果我试图做相反的事情,在正则表达式中使用负前瞻,就像这样:

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可能不是实现我正在寻找的最佳方式为了。

4

2 回答 2

3

这种方法用星号替换所有匹配的字符*。然后,我们迭代替换的字符串并检索与正则表达式字符类不匹配的所有索引。

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 的字符不匹配,因为它们是下划线。

于 2019-03-04T11:12:25.080 回答
2

原因

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

请参阅exec文档

如果您的正则表达式使用“ g”标志,您可以exec()多次使用该方法在同一字符串中查找连续匹配项。当您这样做时,搜索从str正则表达式的lastIndex属性指定的子字符串开始

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

解决方案

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

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);

另外,请参阅如何lastIndex手动移动属性值

于 2019-03-04T11:23:49.207 回答