脏话过滤器,用星号替换脏话的每个字母

问题描述 投票:0回答:2

我有一个工作函数,它获取一系列坏词,然后用星号替换坏词。

当我升级到 PHP7 时,我必须使用

preg_replace_callback
,因为
preg_replace
e
修饰符的使用已被弃用。

这就是我的使用方式:

function filterwords($text){
    $filterWords = array("dummy");
    $filterCount = sizeof($filterWords);

    for ($i = 0; $i < $filterCount; $i++) {
        $text = preg_replace('/\b' . $filterWords[$i] . '\b/ie', "str_repeat('*', strlen('$0'))", $text);
    }

    return $text;
}

这是我的新代码:

echo filterwords("I am a dummy");

function filterwords($text) {
    $filterWords = array("dummy");
    $filterCount = sizeof($filterWords);

    for ($i = 0; $i < $filterCount; $i++) {
        $text = preg_replace_callback('/\b' . $filterWords[$i] . '\b/i',
            function ($matches) {
                return str_repeat('*', strlen('$0'));
            },
            $text
        );  
    }

   return $text;
}

这输出

I am a **
,但我想要的输出是
I am a *****
(有5个星号而不是2个)。

php regex preg-replace preg-replace-callback profanity
2个回答
1
投票

preg_replace
中使用的反向引用(如
$0
)在
preg_replace_callback
中没有任何意义。您将匹配项作为
$matches
传递到函数中,但您正在检查
strlen('$0')
,这只是一个 2 个字符的字符串
$0
,因此您得到 2
*

使用

$matches
和反向引用的编号。就像您习惯的那样,
0
是完整匹配:

return str_repeat('*', strlen($matches[0]));

0
投票

如果您使用

preg_replace_callback()
(继续元字符),还可以避免黑名单单词的循环以及避免
\G
。使用前瞻来定位数组中的所有整个单词,然后匹配第一个单词字符(字母、数字或下划线),然后匹配每个连续的字母并替换为单个星号。

代码:(演示

function filterwords(string $text, array $bannedWords)
{
    return preg_replace(
        '/(?=\b(?:' . implode('|', $bannedWords) . ')\b)\w|\G(?!^)\w/i',
        '*',
        $text
    );
}

echo filterwords("I am a dummy, but I'm not dumb", ['dummy']);
// I am a *****, but I'm not dumb
© www.soinside.com 2019 - 2024. All rights reserved.