目前,我正在研究一个不和谐的机器人,它正在过滤消息。我的问题是在尝试过滤其他包含的单词时发生的,从而触发重复的消息。
这是我的filter.txt:
sad
sadness
sadnesses因为“悲伤”也可以在“悲伤”中找到,所以每当写“悲伤”时,我都会得到“悲伤”的假阳性。
是否可能只检测消息中的确切字符串?就像:I want to be happy, because sadness is bad→‘只是发现悲伤’
我希望你能理解我的意思。
代码:
public void onGuildMessageReceived(GuildMessageReceivedEvent e) {
File file = new File("src/filter.txt");
try {
BufferedReader br = new BufferedReader(new FileReader(file));
String line;
while ((line = br.readLine()) != null) {
if(!line.startsWith("#")) {
if(e.getMessage().getContentRaw().contains(line)) {
User user = e.getJDA().getUserById(e.getAuthor().getIdLong());
e.getMessage().delete().queue();
user.openPrivateChannel().queue(privateChannel -> {
privateChannel.sendMessage("Bitte achte auf deine Sprache!").queue();
});
}
}
}
} catch (IOException e1) {}
}发布于 2020-08-30 12:21:55
正如红衣主教莫妮卡和哈迪斯已经说过的,你应该看看regex。
“‘Regex”表示“正则表达式”,并描述字符串的搜索模式。
您可以使用regex做很多事情,所以如果您想了解更多关于regex的信息,请查看教程。
(这是我在谷歌搜索时第一次发现,你当然可以使用任何你喜欢的教程。)
对于您的用例,我建议如下:
首先,不要使用String.contains(),因为它只适用于String,而不是regex。
与以下正则表达式一起使用String.matches():
"(?is).*\\bSTRING\\b.*"因为有一些逃逸操作,所以没有正则表达式,这就是它的样子:
(?is).*\bSTRING\b.*我会解释它是如何工作的。
\b
\b匹配一个单词边界。单词是a - z,A - Z,0 - 9和_.这个字符的任何组合都被认为是一个单词。
这样做的好处是,在以下情况下,您可以匹配“悲伤”一词:
.→并不影响检测。.*的影响。)当使用“悲伤”时,它将与“悲伤”一词不相匹配,因为“悲伤”一词随后会继续使用:
.*
.匹配除某些换行符以外的任何字符。((?s)在这里帮助我。)
*基本上说,它前面的部分发生0次或更多次。
通过在字符串前后使用.*,正则表达式可以用于字符串周围的任何字符或字符组合(包括没有字符)。
这一点很重要,因为这样的话,单词就可以放在每个可以想象的句子中,而且无论发生什么事情,总是匹配的。
(?is)
?i和?s启用了某些模式。
?i使正则表达式不敏感。这意味着,不管是悲伤,悲伤还是悲伤,这三者都会匹配。
?s启用了“单行模式”,这仅仅意味着.也匹配所有的换行。
?i和?s可以组合成(?is),然后放在正则表达式的前面。
与STRING不同,您只需插入这样的单词:
"(?is).*\\b" + line + "\\b.*"您的代码最终将如下所示:
public void onGuildMessageReceived(GuildMessageReceivedEvent e) {
File file = new File("src/filter.txt");
try {
BufferedReader br = new BufferedReader(new FileReader(file));
String line;
while ((line = br.readLine()) != null) {
if(!line.startsWith("#")) {
if(e.getMessage().getContentRaw().matches("(?is).*\\b" + line + "\\b.*")) {
User user = e.getJDA().getUserById(e.getAuthor().getIdLong());
e.getMessage().delete().queue();
user.openPrivateChannel().queue(privateChannel -> {
privateChannel.sendMessage("Bitte achte auf deine Sprache!").queue();
});
}
}
}
} catch (IOException e1) {}
}如果希望每条消息只生成一条消息(因此在第一次匹配之后停止),则只需在匹配一个单词并将消息发送给用户之后插入一个return;。
发布于 2020-08-31 09:18:52
您也可以尝试使用字符串搜索算法(如阿霍-科拉西克 ),但这需要实现一个正确的签名表。这样的算法在一个更大的单词列表中会更好。
请注意,这样的算法很容易被绕过。简单地添加空格或使用1337字符替换会比简单的单词筛选器更聪明。
https://stackoverflow.com/questions/63650860
复制相似问题