我有一个用例,我需要允许通过任意正则表达式处理任意字符串数组,该正则表达式由正则表达式文字或new RegExp()
构造函数创建。
一切正常,直到全局g
标志与捕获组一起使用。
我在SO上读了几个答案,建议的解决方案是在while循环中使用regex.exec(string),例如 How do you access the matched groups in a JavaScript regular expression?,JavaScript regular expressions and sub-matches
我也在IRC上讨论过这个问题,并建议不要一起实施:
但除非你这样做,否则你的引擎会出现段错误 使用spidermonkey。
所以这是一个角落的情况,尝试将它粘贴到小提琴或者傻瓜,甚至是控制台,它只是打破了:
var regexString = '([^-]*)';
var flags = 'ig';
var regex = new RegExp(regexString, flags);
var arr = ['some-property-image.png', 'another-prop-video.png', 'y-no-work.bmp'];
var result = [];
arr.forEach(function(item) {
var match;
var inter = [];
while (match = regex.exec(item)) {
inter.push(match[0]);
}
});
console.log(result);

我在regex101.com https://regex101.com/r/xG0cL4/1上尝试过
即使我没有量词,即/([^-])/g
https://regex101.com/r/yT7sQ2/1
我的问题:对任意字符串处理任意正则表达式的(correct|safe)
方式是什么?
答案 0 :(得分:1)
它不起作用,因为当' - '到达时,exec()无法匹配' - '字符,但匹配0个字符(因为*),所以它不会跳过它,因此它会被卡住。如果您使用-|([^-]*)
,则会跳过' - '字符。然后,您需要检查' match.index'财产,看看你是否达到了目的。
此外,如果您的目的是保存匹配的文字,则应添加match[1]
而不是match[0]
。
这有效:
var regexString = '-|([^-]*)'; // or better yet: '([^-]+)' will work also
var flags = 'ig';
var regex = new RegExp(regexString, flags);
var arr = ['some-property-image.png', 'another-prop-video.png', 'y-no-work.bmp'];
var result = [];
arr.forEach(function(item) {
var match;
var inter = [];
while (match = regex.exec(item)) {
if (match.index >= item.length) break;
else if (match[1] !== void 0) inter.push(match[1]);
}
});
console.log(result);
但为什么不使用' match()'代替?
var regexString = '[^-]+';
var flags = 'gi';
var regex = new RegExp(regexString, flags);
var arr = ['some-property-image.png', 'another-prop-video.png', 'y-no-work.bmp'];
var result = [];
arr.forEach(function(item) {
var inter = item.match(regex);
});
console.log(result);
答案 1 :(得分:0)
match
对象具有index
属性,其中包含当前匹配的位置。如果在循环中的两个调用之间保持不变,则意味着您被卡住了。
var regexString = '([^-]*)';
var flags = 'ig';
var regex = new RegExp(regexString, flags);
var arr = ['some-property-image.png', 'another-prop-video.png', 'y-no-work.bmp'];
var result = [];
arr.forEach(function(item) {
var match;
var inter = [];
var lastIndex = -1;
while (match = regex.exec(item)) {
if (match.index == lastIndex) {
break;
}
lastIndex = match.index;
inter.push(match[0]);
}
result.push(inter);
});
console.log(result);

答案 2 :(得分:0)
为什么它会崩溃:通过在具有零宽度匹配的循环中使用带有全局标志和exec
的RegExp对象来创建无限循环。循环命中第一个' - '但由于否定的字符类而与该字符不匹配。然后它恢复为零长度匹配,因此不会提前exec
的索引值。这意味着在下一个循环中,它会在相同的位置重新开始,完成同样的事情......无限。
那就是说,很难说出你究竟想要什么,但为什么不试试match
呢?看起来你只关心匹配的字符串,所以exec
似乎有点矫枉过正。
如果所需输出是输入数组的一对一结果数组:
function foo(regexp, strings) {
return strings.reduce(function(matches, str) {
matches.push(str.match(regexp));
return matches;
}, []);
}
foo(/([^-]+)/ig, arr);
// outputs: [["some","property","image.png"],["another","prop","video.png"],["y","no","work.bmp"]]
foo(new RegExp('([^-]+)', 'ig'), arr);
// outputs: [["some","property","image.png"],["another","prop","video.png"],["y","no","work.bmp"]]
即使零宽度匹配,它也不会进入无限循环:
foo(/([^-]*)/ig, arr));
// outputs: [["some","","property","","image.png",""],["another","","prop","","video.png",""],["y","","no","","work.bmp",""]]
如果所需的输出确实是所有匹配的一个数组:
function foo(regexp, strings) {
return strings.reduce(function(matches, str) {
return matches.concat(str.match(regexp));
}, []);
}
foo(/([^-]+)/ig, arr);
// outputs: ["some","property","image.png","another","prop","video.png","y","no","work.bmp"]
foo(new RegExp('([^-]+)', 'ig'), arr);
// outputs: ["some","property","image.png","another","prop","video.png","y","no","work.bmp"]
foo(/([^-]*)/ig, arr));
// outputs: ["some","","property","","image.png","","another","","prop","","video.png","","y","","no","","work.bmp",""]