正则表达式已包含感叹号匹配规则为何无法匹配带感叹号的兑换码
问题根因
- 字符串转义错误:你通过字符串拼接生成正则表达式时,直接写的
'\b'会被JavaScript解析为字符串中的退格转义字符,而非正则语法里的单词边界标识,要生成正则可用的\b需要写成'\\b'做两层转义。 - 单词边界规则不适配场景:正则中的
\b仅会匹配「单词字符(大小写字母、数字、下划线)」和「非单词字符」的交界,!属于非单词字符,如果兑换码以!开头或结尾,边界匹配会直接失败,哪怕你已经把!加到了字符匹配范围里也不会生效。
修复方案
把原生单词边界匹配替换为自定义边界规则,同时修正转义问题,另外给正则加上全局匹配修饰符,避免只匹配帖子里的第一个兑换码。
修复后完整代码
// 可直接在线运行 "use strict"; async function main() { let https = require('https') let url_search_loot = 'https://www.reddit.com/r/idlechampions/search.json?q=flair_name%3A%22loot%22&restrict_sr=1&sort=new' let code_one_letter_range = '0-9a-zA-Z!' let code_one_letter_rx = '[' + code_one_letter_range + ']' let code_one_letter_not_rx = '[^' + code_one_letter_range + ']' let patterns = [ // 4组4位字符用-连接:XXXX-XXXX-XXXX-XXXX Array(4).fill(code_one_letter_rx + '{4}').join('-'), // 3组4位字符用-连接:XXXX-XXXX-XXXX Array(3).fill(code_one_letter_rx + '{4}').join('-'), // 无短横线16位字符 code_one_letter_rx + '{16}', // 无短横线12位字符 code_one_letter_rx + '{12}', ] // 替换原有的\b边界为自定义边界,匹配字符串开头/非允许字符作为起止边界 const startBoundary = `(^|${code_one_letter_not_rx})` const endBoundary = `($|${code_one_letter_not_rx})` patterns.forEach((val, idx, array) => array[idx] = `${startBoundary}(${val})${endBoundary}`) // 加g修饰符全局匹配 let all_patterns = RegExp(patterns.join('|'), 'g') function https_get_promise(url, resolve, reject) { return https.get(url_search_loot, (res) => { let data = ''; res.on('data', (chunk) => data += chunk) res.on('end', () => { res.data = data resolve(res) }) }).on('error', (err) => reject(err)) } let request = new Promise((resolve, reject) => https_get_promise(url_search_loot, resolve, reject)) let res = await request let res_obj = JSON.parse(res.data) let errors = [] res_obj.data.children.forEach((post, idx) => { let matches = [...post.data.selftext.matchAll(all_patterns)] if (!matches || matches.length === 0) { errors.push(post) } else { // 提取匹配到的兑换码,跳过前后边界的捕获组 matches.forEach(match => { const code = match.slice(2).find(v => v != null) console.log(code) }) } }) if (errors.length > 0) { console.log("\n\n\n=== Errors ===") for (const post of errors) { console.log(post.data.selftext) console.log('======') } } } main()
内容的提问来源于stack exchange,提问作者Rocket J
相关产品推荐
相关产品推荐

