我有一个工作函数,它获取一系列坏词,然后用星号替换坏词。
当我升级到 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;
}
此输出 “我是 **” 但我想要的输出是 “我是 *****”(有 5 个星号而不是 2 个)。
preg_replace
中使用的反向引用(如$0
)在preg_replace_callback
中没有任何意义。您将匹配项作为 $matches
传递到函数中,但您正在检查 strlen('$0')
,这只是一个 2 个字符的字符串 $0
,因此您得到 2 *
。
使用
$matches
和反向引用的编号。就像您习惯的那样,0
是完整匹配:
return str_repeat('*', strlen($matches[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