有没有办法让 content.replace 将它们分成比这些更多的词?

is there a way for the content.replace to sort of split them into more words than these?

const filter = ["bad1", "bad2"];

client.on("message", message => {
    var content = message.content;
    var stringToCheck = content.replace(/\s+/g, '').toLowerCase();

    for (var i = 0; i < filter.length; i++) {
        if (content.includes(filter[i])){  
            message.delete();
            break
        }
    }
});

所以我上面的代码是一个不和谐的机器人,它会在有人写''bad1''''bad2''时删除单词 (我要添加一些经过过滤的坏词)幸运的是没有任何错误。

但现在机器人只会删除这些以小写字母书写且中间没有空格或特殊字符的单词。

我想我已经找到了一个解决方案,但我似乎无法将它放入我的代码中,我的意思是我尝试了不同的方法,但它要么删除了小写单词,要么根本没有反应,而是出现了如下错误''cannot read property of undefined''等

var badWords = [
  'bannedWord1',
  'bannedWord2',
  'bannedWord3',
  'bannedWord4'
];

bot.on('message', message => {
  var words = message.content.toLowerCase().trim().match(/\w+|\s+|[^\s\w]+/g);
  var containsBadWord = words.some(word => {
    return badWords.includes(word);
  });

这就是我正在看的。 var words 行。具体来说 (/\w+|\s+|[^\s\w]+/g);.

无论如何要将其实现到我的 const 过滤器代码 (top/above) 或其他方法中? 提前致谢。

嗯,我不确定你想用 .match(/\w+|\s+|[^\s\w]+/g) 做什么。这是一些不必要的正则表达式,只是为了得到一个单词数组 and spaces。如果有人将他们的坏词拆分为“t h i s”之类的词,它甚至不会起作用。

如果您希望过滤器不区分大小写并考虑 spaces/special 个字符,更好的解决方案可能需要多个正则表达式,并分别检查拆分字母和正常的坏词检查。而且你需要确保你的拆分字母检查是准确的,否则像“wash it”这样的词可能会被认为是一个坏词,尽管单词之间有 space。

一个解决方案

所以这是一个可能的解决方案。请注意,它只是 a 解决方案,远非唯一的解决方案。我将使用硬编码的字符串示例而不是 message.content,以使其成为工作片段:

//Our array of bad words
var badWords = [
  'bannedWord1',
  'bannedWord2',
  'bannedWord3',
  'bannedWord4'
];

//A function that tests if a given string contains a bad word
function testProfanity(string) {

  //Removes all non-letter, non-digit, and non-space chars
  var normalString = string.replace(/[^a-zA-Z0-9 ]/g, "");
  
  //Replaces all non-letter, non-digit chars with spaces
  var spacerString = string.replace(/[^a-zA-Z0-9]/g, " ");

  //Checks if a condition is true for at least one element in badWords
  return badWords.some(swear => {
  
    //Removes any non-letter, non-digit chars from the bad word (for normal)
    var filtered = swear.replace(/\W/g, "");
    
    //Splits the bad word into a 's p a c e d' word (for spaced)
    var spaced = filtered.split("").join(" ");
    
    //Two different regexes for normal and spaced bad word checks
    var checks = {
      spaced: new RegExp(`\b${spaced}\b`, "gi"),
      normal: new RegExp(`\b${filtered}\b`, "gi")
    };
    
    //If the normal or spaced checks are true in the string, return true
    //so that '.some()' will return true for satisfying the condition
    return spacerString.match(checks.spaced) || normalString.match(checks.normal);
  
  });

}

var result;

//Includes one banned word; expected result: true
var test1 = "I am a bannedWord1";
result = testProfanity(test1);

console.log(result);

//Includes one banned word; expected result: true
var test2 = "I am a b a N_N e d w o r d 2";
result = testProfanity(test2);

console.log(result);

//Includes one banned word; expected result: true
var test3 = "A bann_eD%word4, I am";
result = testProfanity(test3);

console.log(result);

//Includes no banned words; expected result: false
var test4 = "No banned words here";
result = testProfanity(test4);

console.log(result);

//This is a tricky one. 'bannedWord2' is technically present in this string,
//but is 'bannedWord22' really the same? This prevents something like
//"wash it" from being labeled a bad word; expected result: false
var test5 = "Banned word 22 isn't technically on the list of bad words...";
result = testProfanity(test5);

console.log(result);

我对每一行都进行了彻底的注释,以便您了解我在每一行中所做的事情。又来了,没有评论或测试部分:

var badWords = [
  'bannedWord1',
  'bannedWord2',
  'bannedWord3',
  'bannedWord4'
];

function testProfanity(string) {

  var normalString = string.replace(/[^a-zA-Z0-9 ]/g, "");
  var spacerString = string.replace(/[^a-zA-Z0-9]/g, " ");

  return badWords.some(swear => {
  
    var filtered = swear.replace(/\W/g, "");
    var spaced = filtered.split("").join(" ");
    
    var checks = {
      spaced: new RegExp(`\b${spaced}\b`, "gi"),
      normal: new RegExp(`\b${filtered}\b`, "gi")
    };
    
    return spacerString.match(checks.spaced) || normalString.match(checks.normal);
  
  });

}

说明

如您所见,此过滤器能够处理各种标点符号、大写字母,甚至是坏词字母之间的单个 spaces/symbols。但是,请注意,为了避免我描述的“清洗它”场景(可能导致无意中删除干净的消息),我这样做是为了让“bannedWord22”之类的东西不会被视为与“bannedWord2”相同。如果您希望它做相反的事情(因此将“bannedWord22”视为与“bannedWord2”相同),则必须删除正常检查正则表达式中的两个 \b 短语。

我也会解释正则表达式,这样你就可以完全理解这里发生的事情了:

  • [^a-zA-Z0-9 ] 表示“select 任何不在 a-z、A-Z、0-9 或 space 范围内的字符”(意味着所有不在指定范围内的字符都将被替换为空字符串,实质上是将它们从字符串中删除)。
  • \W 表示“select 不是单词字符的任何字符”,其中“单词字符”是指 a-z、A-Z、0-9 和下划线范围内的字符。
  • \b 表示“单词边界”,本质上表示单词何时开始或停止。这包括 spaces、行首和行尾。 \b 使用额外的 \ 进行转义(成为 \b),以防止 javascript 将正则表达式标记与字符串的转义序列混淆。
  • 两个正则表达式检查中使用的标志 gi 分别指示“全局”和“不区分大小写”。

当然,要使它与您的 discord 机器人一起工作,您在消息处理程序中所要做的就是这样(并确保将 badWords 替换为您的 filter 变量testProfanity()):

if (testProfanity(message.content)) return message.delete();

如果您想了解有关正则表达式的更多信息,或者想弄乱它 and/or 测试一下,this 是一个很好的资源。