我有一个通过5/7单元测试的Codepen。卡在以非数字字符开头的字符串上。
https://codepen.io/david-grieve/pen/pBpGoO?editors=0012
var regexString = /^\D*(?!(\s*\d\s*){10,}).*/;
var regexString = /^\D*(?!(\s*\d\s*){10,}).*/;
var tests = [{
text: 'abc123',
ismatch: true
}, {
text: '1234567890',
ismatch: false
}, {
text: '123456789',
ismatch: true
}, {
text: 'abc1234567890efg',
ismatch: false
}, {
text: '123 456 789 123',
ismatch: false
},
{
text: 'abc1234567890',
ismatch: false
}, {
text: '1234567890efg',
ismatch: false
}
];
console.log(new Date().toString());
tests.map(test => console.log(test.text, regexString.test(test.text) == test.ismatch));
使用此正则表达式,以下字符串通过了单元测试
这些未通过单元测试
注意:/^\D{3,}(?!(\s*\d\s*){10,}).*/通过所有测试,但显然是错误的。
答案 0 :(得分:1)
^\D*(?!
的问题在于,即使在负前瞻中找到了长数字/空格字符串,与\D
匹配的部分也只会 backtrack 一个字符一旦负前瞻匹配。例如,何时
^\D*(?!\d{10,}).*
匹配
abc1234567890
\D*
匹配ab
,而.*
匹配c1234567890
。 b
和c
之间的位置不是立即,后跟一个长数字/空格子字符串,因此匹配不会失败。
此外,由于某些数字可能会在连续的10位数字之前出现,因此开头的^\D*
是不够的-例如,如果输入是{{1} }?而是尝试
1a01234567890
这可以确保每个位置都不会跟随(10位数字,可能用空格分隔)。
https://regex101.com/r/v7t4IC/1
如果数字只能出现在字符串的单个块中(可能用空格隔开),那么如果您在支持 possitive 量词的环境中使用该模式就可以了,这可以防止回溯,例如:
^(?!.*(\d\s*){10}).*
https://regex101.com/r/eGdw2l/1
(不幸的是Javascript不支持这种语法)