Discord.js实现忽略标点检测末尾独立完整单词及代码优化
优化Discord机器人的触发逻辑:精准匹配句末/独立消息的目标单词
问题描述
我想要实现一个Discord机器人,当消息包含特定单词(满足位于句末、单独成消息,忽略标点)时触发响应,但如果单词和其他单词粘连(比如"Eyes"里的"yes")则不响应。举个例子:目标单词是"yes"时,"I said yes !"、"Yes"会触发,"Eyes"不会。
我当前的实现代码如下:
const Discord = require('discord.js'); const client = new Discord.Client(); client.once('ready', () => { console.log(`Online`); }); const responseObject = { "yes": "ok !", "no": "potato !" }; client.on('message', message => { var regex = /[!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~]/g; var regexx = /[ \t]+$/g; message.content = message.content.toLowerCase(); message.content = message.content.replace(regex, '') message.content = message.content.replace(regexx, '') if(responseObject[message.content]) { message.channel.send(responseObject[message.content]); } });
想问问有没有更优的代码优化方案?
优化方案
嘿,你的思路方向是对的,但确实有更简洁、更健壮的优化方式,主要可以从正则匹配的精准性和代码简洁性入手:
1. 用单个正则完成精准匹配,减少冗余操作
你的现有代码是通过多次字符串替换来清理内容,再做完全匹配,但其实可以直接用一个正则表达式,一次性判断目标单词是否是消息的最后一个有效部分——不管后面有没有标点或空格,同时还能避免匹配粘连的单词。
优化后的代码如下:
const Discord = require('discord.js'); const client = new Discord.Client(); client.once('ready', () => { console.log(`Online`); }); const responseObject = { "yes": "ok !", "no": "potato !" }; // 提取所有目标单词,构建动态正则 const targetWords = Object.keys(responseObject); // 正则说明: // ^.*? :非贪婪匹配开头的任意内容(避免吃掉前面的字符) // \b(${targetWords.join('|')})\b :匹配完整的目标单词(\b是词边界,防止粘连) // [\s\p{P}]*$ :匹配末尾任意数量的空格或Unicode标点(覆盖所有语言的标点) // 'i' :忽略大小写,不用手动转小写 const matchRegex = new RegExp( `^.*?\\b(${targetWords.join('|')})\\b[\\s\\p{P}]*$`, 'i' ); client.on('message', message => { // 跳过机器人自身的消息,防止循环触发 if (message.author.bot) return; const matchResult = message.content.match(matchRegex); if (matchResult) { // 转小写后匹配响应对象 const matchedWord = matchResult[1].toLowerCase(); message.channel.send(responseObject[matchedWord]); } }); // 别忘了加上登录逻辑(实际运行需要你的token) // client.login('YOUR_BOT_TOKEN');
2. 关键优化点拆解
- 词边界
\b:这是避免匹配粘连单词的核心——它会确保匹配的是独立单词,像"Eyes"里的"yes"就不会被触发,完美符合你的需求。 - Unicode标点
\p{P}:比你手动列举的标点全面得多,能覆盖中文、日文等各种语言的标点符号,不用再担心漏处理特殊标点。 - 忽略大小写标志
i:直接让正则处理大小写匹配,省去了手动将整个消息转小写的步骤,代码更简洁。 - 跳过机器人消息:新增的
if (message.author.bot) return;能避免机器人自己发送的消息触发响应,防止出现无限循环的问题。 - 动态正则构建:如果后续要添加更多目标单词,只需要修改
responseObject,正则会自动更新,扩展性更强。
3. 额外的小建议
- 始终使用
const/let代替var,符合现代JavaScript规范,避免变量提升带来的潜在问题。 - 记得补充机器人的登录代码(
client.login('YOUR_BOT_TOKEN')),不然机器人无法上线运行。
内容的提问来源于stack exchange,提问作者user9598971




