Я работаю над плагином WordPress, который заменяет плохие слова из комментариев случайными новыми из списка.
Теперь у меня есть 2 массива: один содержит плохие слова, а другой – хорошие слова.
$bad = array("bad", "words", "here"); $good = array("good", "words", "here");
Поскольку я новичок, я застрял в какой-то момент.
Чтобы заменить плохие слова, я использовал $newstring = str_replace($bad, $good, $string);
,
Моя первая проблема заключается в том, что я хочу отключить чувствительность к случаю, поэтому я не буду помещать слова как "bad", "Bad", "BAD", "bAd", "BAd", etc
Но мне нужен новый слово, чтобы сохранить формат исходного слова, например, если я напишу «Плохо», он будет заменен словами «Слова», но если я наберу «плохой», он будет заменен словами «слова» и т. д.
Моей первой задачей было использовать str_ireplace
, но она забывает, если оригинальное слово имеет заглавную букву.
Вторая проблема заключается в том, что я не знаю, как обращаться с пользователями, которые типа типа: «плохо», «слова» и т. Д. Мне нужна идея.
Чтобы сделать это, выберите случайное слово, я думаю, что могу использовать $new = $good[rand(0, count($good)-1)];
затем $newstring = str_replace($bad, $new, $string);
, Если у вас есть идея, я здесь, чтобы послушать.
Общий вид моего скрипта:
function noswear($string) { if ($string) { $bad = array("bad", "words"); $good = array("good", "words"); $newstring = str_replace($bad, $good, $string); return $newstring; } echo noswear("I see bad words coming!");
Заранее спасибо за вашу помощь!
Есть (как неоднократно отмечалось в комментариях), чтобы разглядеть целые существа для вас – и / или ваш код – чтобы внедрить такую функцию, чтобы назвать лишь некоторые из них:
Вам лучше реализовать систему модерации / флага, в которой люди могут отмечать оскорбительные комментарии, которые затем могут быть отредактированы / удалены модами, пользователями и т. Д.
По этому пониманию, давайте продолжим …
Учитывая, что вы:
$bad_words
$good_words
Вы можете очень легко использовать функцию preg_replace_callback
PHP
:
$input_string = 'This Could be interesting but should it be? Perhaps this \'would\' work; or couldn\'t it?'; $bad_words = array('could', 'would', 'should'); $good_words = array('might', 'will'); function replace_words($matches){ global $good_words; return $matches[1].$good_words[rand(0, count($good_words)-1)].$matches[3]; } echo preg_replace_callback('/(^|\b|\s)('.implode('|', $bad_words).')(\b|\s|$)/i', 'replace_words', $input_string);
Итак, так, что делает preg_replace_callback
, он компилирует шаблон регулярного выражения, состоящий из всех плохих слов . Матчи будут в формате:
/(START OR WORD_BOUNDARY OR WHITE_SPACE)(BAD_WORD)(WORD_BOUNDARY OR WHITE_SPACE OR END)/i
Модификатор i
делает регистр нечувствительным к регистру, который бы соответствовал как bad
и Bad
.
Функция replace_words
затем берет согласованное слово и его границы (пробел или символ пробела) и заменяет его границами и случайным хорошим словом .
global $good_words; <-- Makes the $good_words variable accessible from within the function $matches[1] <-- The word boundary before the matched word $matches[3] <-- The word boundary after the matched word $good_words[rand(0, count($good_words)-1] <-- Selects a random good word from $good_words
Вы можете переписать выше как один вкладыш, используя анонимную функцию в preg_replace_callback
echo preg_replace_callback( '/(^|\b|\s)('.implode('|', $bad_words).')(\b|\s|$)/i', function ($matches) use ($good_words){ return $matches[1].$good_words[rand(0, count($good_words)-1)].$matches[3]; }, $input_string );
Если вы собираетесь использовать его несколько раз, вы также можете записать его как автономную функцию, хотя в этом случае вы, скорее всего, захотите передать хорошие / плохие слова функции при вызове (или жесткий код их там постоянно), но это зависит от того, как вы их вывести …
function clean_string($input_string, $bad_words, $good_words){ return preg_replace_callback( '/(^|\b|\s)('.implode('|', $bad_words).')(\b|\s|$)/i', function ($matches) use ($good_words){ return $matches[1].$good_words[rand(0, count($good_words)-1)].$matches[3]; }, $input_string ); } echo clean_string($input_string, $bad_words, $good_words);
Выполняя указанные выше функции последовательно со списками ввода и слова, показанными в первом примере:
This will be interesting but might it be? Perhaps this 'will' work; or couldn't it? This might be interesting but might it be? Perhaps this 'might' work; or couldn't it? This might be interesting but will it be? Perhaps this 'will' work; or couldn't it?
Конечно, замещающие слова выбираются случайным образом, поэтому, если обновить страницу, я получу что-то еще … Но это показывает, что / не заменяется.
$bad_words
foreach($bad_words as $key=>$word){ $bad_words[$key] = preg_quote($word); }
\b
В этом коде я использовал \b
, \s
и ^
или $
как границы слов, для этого есть веская причина. Хотя white space
, start of string
и end of string
считаются границами слов \b
, не будут совпадать во всех случаях, например:
\b\$h1t\b <---Will not match
Это связано с тем, что \b
соответствует символам без слов (т.е. [^a-zA-Z0-9]
), а символы типа $
не считаются символами слова .
В зависимости от размера вашего списка слов есть пара потенциальных икота. С точки зрения дизайна системы, как правило, плохая форма имеет огромное количество регулярных выражений по нескольким причинам:
Учитывая, что шаблон регулярного выражения скомпилирован PHP
первая причина отрицается. Второе должно быть также отрицательно; если вы – список слов большой с дюжиной перестановок каждого плохого слова, то я предлагаю вам остановиться и переосмыслить ваш подход (читайте: используйте систему флагов / модерации).
Чтобы уточнить, я не вижу проблемы с небольшим списком слов, чтобы отфильтровать конкретные ругательства, поскольку он служит цели: остановить пользователей от вспышки друг у друга; проблема возникает, когда вы пытаетесь отфильтровать слишком много, включая перестановки. Придерживайтесь фильтрации обычных ругательных слов, и если это не сработает, то – в последний раз – внедрить систему маркировки / модерации.
Я подошел к этому методу, и он работает нормально. Возвращение true , если в записи есть запись плохих слов.
Пример:
function badWordsFilter($inputWord) { $badWords = Array("bad","words","here"); for($i=0;$i<count($badWords);$i++) { if($badWords[$i] == strtolower($inputWord)) return true; } return false; }
Применение:
if (badWordsFilter("bad")) { echo "Bad word was found"; } else { echo "No bad words detected"; }
Поскольку слово «плохое» занесено в черный список, оно будет эхом.
ИЗМЕНИТЬ 1:
Как было предложено, можно также выполнить простой in_array
check:
function badWordsFilter($inputWord) { $badWords = Array("bad","words","here"); if(in_array(strtolower($inputWord), $badWords) ) { return true; } return false; }
EDIT 2:
Как я и обещал, я подошел к немного другой идее о замене плохих слов хорошими словами, как вы упомянули в своем вопросе. Надеюсь, это поможет вам немного, но это лучшее, что я могу предложить на данный момент, так как я совершенно не уверен в том, что вы пытаетесь сделать.
Пример:
1. Давайте объединим массив с плохими и хорошими словами в один
$wordsTransform = array( 'shit' => 'ship' );
2. Ваш мнимый ввод пользователя
$string = "Rolling In The Deep by Adel\n \n There's a fire starting in my heart\n Reaching a fever pitch, and it's bringing me out the dark\n Finally I can see you crystal clear\n Go ahead and sell me out and I'll lay your shit bare";
3. Замена плохих слов хорошими словами
$string = strtr($string, $wordsTransform);
4. Получение желаемого результата
Идя ко дну
Огонь разжигается в моем сердце
Достигнув высоты лихорадки, и она выводит меня из темноты
Теперь я тебя прекрасно вижу
Идите вперед и продайте меня, и я закрою ваше судно
ИЗМЕНИТЬ 3:
Чтобы следовать правильному комментарию от Wrikken , я полностью забыл о том, что strtr
чувствителен к регистру и что лучше следовать границе слова. Я привел следующий пример из
PHP: strtr – вручную и немного изменил его.
Такая же идея, как и в моем втором редактировании, но не зависящая от регистра, проверяет границы слова и помещает обратную косую черту перед каждым символом, который является частью синтаксиса регулярных выражений:
1. Способ:
// // Written by Patrick Rauchfuss class String { public static function stritr(&$string, $from, $to = NULL) { if(is_string($from)) $string = preg_replace("/\b{$from}\b/i", $to, $string); else if(is_array($from)) { foreach ($from as $key => $val) self::stritr($string, $key, $val); } return preg_quote($string); // return and add a backslash to special characters } }
2. Массив с плохими и хорошими словами
$wordsTransform = array( 'shit' => 'ship' );
3. Замена
String::stritr($string, $wordsTransform);