-2

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

例如:

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 太棒了!

感谢所有的答案!

4

5 回答 5

3

您可以将审查后的单词放在基于键的数组中,并且数组的值应该是 char 替换为的位置*(请参见$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:在我的本地 PC 机器上添加了速度测试循环和结果。

于 2013-08-14T17:29:47.537 回答
2

制作一组单词和替换。就处理而言,这应该是您最快的选择,但设置起来更有条理。请记住,当您设置模式以使用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*script。如果您认识在日常工作中使用 j*v*scripting 的人,您可以向他们询问有关成为编写 J*v*Scripts 的程序员的问题。взл*м прохладно

更新

它对 UTF-8 字符的工作方式相同,请注意,您必须指定一个u修饰符才能使模式被视为 UTF-8。

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

于 2013-08-14T19:06:49.587 回答
1

为什么不只使用一个小辅助函数并传递一个单词和所需的审查器呢?

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!

另一个演示

于 2013-08-14T17:21:09.113 回答
0

您可以在某处存储被删减词的小写列表,如果您每次都可以在第二个字母上加星标,请执行以下操作:

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);
}
于 2013-08-14T17:11:07.113 回答
0

这就是我要做的:

  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,最后用---. (或者你选择用什么来分隔你的桌子。)

希望这有帮助!

于 2013-08-14T17:26:41.543 回答