首页 > 解决方案 > 正则表达式:正负前瞻 (JS)

问题描述

我被困在 Free Code Camp 上的这个问题上。看了讨论室的各种解释,问了朋友,还是不明白。

挑战:在 pwRegex 中使用前瞻来匹配长度大于 5 个字符且具有两个连续数字的密码。

回答:

 let sampleWord = "astronaut";
 let pwRegex = /(?=\w{5,})(?=\D*\d{2})/;
 let result = pwRegex.test(sampleWord);

我不明白必须写 \D* 来查找两个连续数字的原因。为什么 d{2} 不够?

标签: javascriptregexlookahead

解决方案


实际上,答案是错误的 - 如果有一个数字,然后是非数字(或某种组合),然后是 2 个数字,则正则表达式将失败。例如:

const sampleWord = "a1b23";
const pwRegex = /(?=\w{5,})(?=\D*\d{2})/;
console.log(pwRegex.test(sampleWord));

这是因为\D匹配非数字字符- 它不匹配数字,因此它不会正确匹配 inital 。a2b

要回答您的问题,\d{2}在它之前而不是重复字符需要两个数字位于字符串的开头(或其他错误的地方):

const re = /(?=\w{5,})(?=\d{2})/;
console.log(re.test('23foo'));
console.log(re.test('foo23'));

另一个问题(可能只是拼写错误或错误复制的摘要)是“长度超过 5 个字符”意味着“至少 6 个字符”,所以你需要\w{6},而不是\w{5}. (不需要\w{6,},只要匹配前6个就足够了)

为了解决这个问题,在第二次前瞻中,重复任何字符后跟两位数,因为您不知道哪些字符可能出现在两位数的子字符串之前。此外,如果字符串开头的位置不匹配,最好让正则表达式立即失败(因为如果位置 0 不匹配,那么假设字符串由单词字符组成,那么其他位置也不会匹配)。因此,用于^指示字符串开始锚点:

const re = /^(?=\w{6,})(?=.*\d{2})/;
console.log(re.test('23foob'));
console.log(re.test('foob23'));
console.log(re.test('aa1b23'));


推荐阅读