我有过滤器可以过滤坏话,比如'屁股''他妈的'等等。现在我正试图处理像“f * ck”,“sh / t”这样的漏洞。
我能做的一件事就是将每个单词与具有这些漏洞的坏词的词典相匹配。但这是非常静态而且不是很好的方法。
我能做的另一件事就是使用levenshtein距离。应该阻止levenshtein距离= 1的单词。但这种方法也容易产生误报。
if(!ctype_alpha($text)&& levenshtein('shit', $text)===1)
{
//match
}
我正在寻找使用正则表达式的一些方法。也许我可以将levenshtein距离与regex
结合起来,但我无法理解。
任何建议都非常值得赞赏。
答案 0 :(得分:3)
如评论中所述,很难做到这一点。这个片段远非完美,它将检查匹配字母代替相同数量的其他字符的匹配。
它可能会让你大致了解如何解决这个问题,尽管如果你想让它更聪明,还需要更多的逻辑。例如,此过滤器不会过滤'fukk','f ck','f ** ck','fck','。fuck'(带有前导点)或'fück',而它可能会过滤'+' +++'用'beep'代替它。但它也会过滤'f * ck','f ** k','f * cking'和'sh1t',所以它可能会变得更糟。 :)
让它变得更好的一种简单方法是以更智能的方式分割字符串,因此标点符号不会粘贴到它们所邻接的单词上。另一个改进可能是从每个单词中删除所有非字母字符,并检查其余单词是否在单词中的顺序相同。那样,'f \ / ck'也会匹配'fuck'。无论如何,让你的想象力疯狂,但要小心误报。相信我,“他们”总能找到一种方式来绕过你的过滤器来表达自己。
<?php
$badwords = array('shit', 'fuck');
$text = 'Man, I shot this f*ck, sh/t! fucking fucker sh!t fukk. I love this. ;)';
$words = explode(' ', $text);
// Loop through all words.
foreach ($words as $word)
{
$naughty = false;
// Match each bad word against each word.
foreach ($badwords as $badword)
{
// If the word is shorter than the bad word, it's okay.
// It may be bigger. I've done this mainly, because in the example given,
// 'f*ck,' will contain the trailing comma. This could be easily solved by
// splitting the string a bit smarter. But the added benefit, is that it also
// matches derivatives, like 'f*cking' or 'f*cker', although that could also
// result in more false positives.
if (strlen($word) >= strlen($badword))
{
$wordOk = false;
// Check each character in the string.
for ($i = 0; $i < strlen($badword); $i++)
{
// If the letters don't match, and the letter is an actual
// letter, this is not a bad word.
if ($badword[$i] !== $word[$i] && ctype_alpha($word[$i]))
{
$wordOk = true;
break;
}
}
// If the word is not okay, break the loop.
if (!$wordOk)
{
$naughty = true;
break;
}
}
}
// Echo the sensored word.
echo $naughty ? 'beep ' : ($word . ' ');
}