PHP单词审查员保留了原来的大写字母


PHP word censor with keeping the original caps

我们想审查我们网站上的某些单词,但每个单词都有不同的审查输出。

例如:

PHP=>p*p,javascript=>j*vascript

(但不总是第二个字母。)

因此,我们想要一个简单的"一颗星"审查制度,但要保留原来的上限。来自数据库的数据是未经审查的,所以我们需要尽可能快的方式。

$data="Javascript and php are awesome!";
$word[]="PHP";
$censor[]="H";//the letter we want to replace
$word[]="javascript";
$censor[]="a"//but only once (j*v*script would look wierd)
//Of course if it needed we can use the full censored word in $censor variables

期望值:J*vascript和p*p太棒了

谢谢你的回答!

您可以将经过审查的单词放在基于关键字的数组中,数组的值应该是用*替换的字符的位置(请参阅下面的$censor数组示例)。

$string = 'JavaSCRIPT and pHp are testing test-ground for TEST ŠĐČĆŽ ŠĐčćŽ!';
$censor = [
    'php' => 2,
    'javascript' => 2,
    'test' => 3,
    'šđčćž' => 4,
];
function stringCensorSlow($string, array $censor) {
    foreach ($censor as $word => $position) {
        while (($pos = mb_stripos($string, $word)) !== false) {
            $string = 
                mb_substr($string, 0, $pos + $position - 1) . 
                '*' . 
                mb_substr($string, $pos + $position);
        }
    }
    return $string;
}
function stringCensorFast($string, array $censor) {
    $pattern = [];
    foreach ($censor as $word => $position) {
        $word = '~(' . mb_substr($word, 0, $position - 1) . ')' . mb_substr($word, $position - 1, 1) . '(' . mb_substr($word, $position) . ')~iu';
        $pattern[$word] = '$1*$2';
    }
    return preg_replace(array_keys($pattern), array_values($pattern), $string);
}

使用示例:

echo stringCensorSlow($string, $censor);
# J*vaSCRIPT and p*p are te*ting te*t-ground for TE*T ŠĐČ*Ž ŠĐč*Ž!
echo stringCensorFast($string, $censor) . "'n";
# J*vaSCRIPT and p*p are te*ting te*t-ground for TE*T ŠĐČ*Ž ŠĐč*Ž!

速度测试:

foreach (['stringCensorSlow', 'stringCensorFast'] as $func) {
    $time = microtime(true);
    for ($i = 0; $i < 10000; $i++) {
        $func($string, $censor);
    }
    $time = microtime(true) - $time;
    echo "{$func}() took $time'n";
}

本地主机上的输出是:

stringCensorSlow() took 1.9752140045166
stringCensorFast() took 0.11587309837341

升级#1:添加了多字节字符安全。

升级#2:添加了preg_replace的示例,它比mb_substr更快。Tnx到AbsoluteƵERæ

升级#3:在我的本地电脑上添加了速度测试循环和结果。

制作一个单词和替换的数组。就处理而言,这应该是最快的选择,但设置起来更有条理。请记住,当您设置模式时,要使用i修饰符使每个模式不区分大小写。您最终可以将这些数据从数据库中提取到阵列中。我已经为这个例子对数组进行了硬编码。

<!DOCTYPE html>
<html>
<meta content="text/html; charset=UTF-8" http-equiv="content-type">
<?php
$word_to_alter = array(
'!(j)a(v)a(script)(s|ing|ed)?!i',
'!(p)h(p)!i',
'!(m)y(sql)!i',
'!(p)(yth)o(n)!i',
'!(r)u(by)!i',
'!(ВЗЛ)О(М)!iu',
);
$alteration = array(
'$1*$2*$3$4',
'$1*$2',
'$1*$2',
'$1$2*$3',
'$1*$2',
'$1*$2',
);
$string = "Welcome to the world of programming. You can learn PHP, MySQL, Python, Ruby, and Javascript all at your own pace. If you know someone who uses javascripting in their daily routine you can ask them about becoming a programmer who writes JavaScripts. взлом прохладно";
$newstring = preg_replace($word_to_alter,$alteration,$string);
echo $newstring;
?>
</html>

输出

欢迎来到编程世界。你可以学习P*P,M*SQL,Pyth*n,R*by和J*v*脚本都按照自己的节奏编写。如果你认识一个在他们的日常生活中使用j*v*脚本,你可以询问他们成为编写J*v*脚本的程序员。

更新

它与UTF-8字符的工作原理相同,请注意,必须指定u修饰符才能将模式视为UTF-8。

u(PCRE_UTF8)此修饰符启用PCRE的附加功能,该功能与Perl不兼容。模式字符串被视为UTF-8。这修饰符可从Unix上的PHP 4.1.0或更高版本以及PHP中获得4.2.3在win32上。从PHP 4.3.5开始检查模式的UTF-8有效性。

为什么不使用一个小助手函数并向其传递一个单词和所需的审查程序?

function censorWord($word, $censor) {
    if(strpos($word, $censor)) {
        return preg_replace("/$censor/",'*', $word, 1);
    }
}
echo censorWord("Javascript", "a"); // returns J*avascript
echo censorWord("PHP", "H"); // returns P*P

然后你可以对照你的单词列表检查这个单词,如果它是一个应该被审查的单词,你可以把它传递给函数。然后,你也总是有原始单词和经过审查的单词可以玩或放回你的句子中。

这也可以通过改变preg_replace中的偏移量来轻松地改变被审查的字母数量。你所要做的就是保留一组单词,在空格或其他地方分解句子,然后检查in_array。如果它在阵列中,则将其发送到censorWord()

演示

这里有一个更完整的例子,完全按照你在OP.中所说的去做

function censorWord($word, $censor) {
    if(strpos($word, $censor)) {
        return preg_replace("/$censor/",'*', $word, 1);
    }
}
$word_list = ['php','javascript'];
$data = "Javascript and php are awesome!";
$words = explode(" ", $data);
// pass each word by reference so it can be modified inside our array
foreach($words as &$word) {
    if(in_array(strtolower($word), $word_list)) {
        // this just passes the second letter of the word
        // as the $censor argument
        $word = censorWord($word, $word[1]);    
    }
}
echo implode(" ", $words); // returns J*vascript and p*p are awesome!

另一个演示

你可以在某个地方存储一个被审查单词的小写列表,如果你每次都能在第二个字母上加上星号,可以这样做:

if (in_array(strtolower($word), $censored_words)) {
    $word = substr($word, 0, 1) . "*" . substr($word, 2);
} 

如果你想更改字母的第一次出现,你可以做一些类似的事情:

$censored_words = array('javascript' => 'a', 'php' => 'h', 'ruby' => 'b');
$lword = strtolower($word);
if (in_array($lword, array_keys($censored_words))) {
    $ind = strpos($lword, $censored_words[$lword]);
    $word = substr($word, 0, $ind) . "*" . substr($word, $ind + 1);
}

这就是我要做的:

  1. 创建一个简单的数据库(文本文件),并制作一个"表格",列出所有经过审查的单词和预期的审查结果。例如:

    PHP --- P*P
    javascript --- j*vascript
    HTML --- HT*L
    
  2. 编写PHP代码,将数据库信息与简单的审查文件进行比较。您必须使用array explode来创建一个仅包含单词的数组。类似这样的东西:

    /* Opening database of censored words */
    $filename = "/files/censored_words.txt";
    $file = fopen( $filename, "r" );
    if( $file == false )
    {
        echo ( "Error in opening file" );
        exit();
    }
    /* Creating an array of words from string*/
    $data = explode(" ", $data); // What was "Javascript and PHP are awesome!" has
                                 // become "Javascript", "and", "PHP", "are", 
                                 // "awesome!". This is useful.
    
  3. 如果您的脚本找到匹配的单词,请将数据中的单词替换为列表中经过审查的单词。您必须首先用'r'n来分隔文件,最后用---来分隔文件。(或者你选择什么来分隔你的桌子。)

希望这能有所帮助!