Intereting Posts
Как применить запятую к числу с десятичной точкой в ​​php mysql_query сохранить тип данных, созданный в таблице при возврате? Обновление подписчиков в списке с использованием cURL и Mailchimp API v3 OAuth – секрет потребителя в приложениях с открытым исходным кодом Что брандмауэр Symfony делает так долго? PHP / SESSION: Логин один на пользователя? Исправить PHP-метод для хранения специальных символов в MySQL DB Идентификатор видео Vimeo YouTube из встроенного кода или URL-адреса с регулярным выражением PHP RegEx Установка функции равна переменной? PHP define (), похоже, не работает с include () Является ли система очереди laravel подходящей для больших проектов? ошибка с использованием include_once в php Получение ошибки в рабочей среде, работающая нормально в localhost Как отсортировать массив PHP объектов по значению внутри объекта в каждом элементе? Использование пользовательского поиска Google с существующим элементом формы

PHP клятвенный фильтр слов

Я работаю над плагином 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!"); 

Заранее спасибо за вашу помощь!

предвестник

Есть (как неоднократно отмечалось в комментариях), чтобы разглядеть целые существа для вас – и / или ваш код – чтобы внедрить такую ​​функцию, чтобы назвать лишь некоторые из них:

  1. Люди будут добавлять символы, чтобы обмануть фильтр
  2. Люди станут творческими (например, инсинуация)
  3. Люди будут использовать пассивную агрессию и сарказм
  4. Люди будут использовать предложения / фразы не только для слов

Вам лучше реализовать систему модерации / флага, в которой люди могут отмечать оскорбительные комментарии, которые затем могут быть отредактированы / удалены модами, пользователями и т. Д.

По этому пониманию, давайте продолжим …

Решение

Учитывая, что вы:

  1. Список запрещенных слов $bad_words
  2. Список замещающих слов $good_words
  3. Хотите заменить плохие слова независимо от случая
  4. Хотите заменить плохие слова случайными хорошими словами
  5. У вас есть правильно сбежавший список неверных слов : см. http://php.net/preg_quote

Вы можете очень легко использовать функцию 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? 

Конечно, замещающие слова выбираются случайным образом, поэтому, если обновить страницу, я получу что-то еще … Но это показывает, что / не заменяется.

NB

$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] ), а символы типа $ не считаются символами слова .

Разное

В зависимости от размера вашего списка слов есть пара потенциальных икота. С точки зрения дизайна системы, как правило, плохая форма имеет огромное количество регулярных выражений по нескольким причинам:

  1. Это может быть трудно поддерживать
    1. Трудно читать / понимать, что он делает
    2. Трудно найти ошибки
  2. Это может быть интенсивным в памяти, если список слишком велик

Учитывая, что шаблон регулярного выражения скомпилирован 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

ИЗМЕНИТЬ 1:

Как было предложено, можно также выполнить простой in_array check:

 function badWordsFilter($inputWord) { $badWords = Array("bad","words","here"); if(in_array(strtolower($inputWord), $badWords) ) { return true; } return false; } 

Пример онлайн 2

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

ИЗМЕНИТЬ 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); 

Пример онлайн 4