Intereting Posts
Как передать несколько переменных в PHP с помощью jQuery Что происходит, когда SimpleXML анализирует XML со специальными символами? Запретная ошибка Heroku 403 Я получаю ошибку, когда я использую mysqli select Функция масштабирования / изменения размера изображения с использованием библиотеки GD измененный объект после хранения или состояние объекта Создание безопасного публичного API с помощью PHP / MYSQL возникают проблемы с сегментом кода функции jqgrid dataUrl Можно ли изменить этот запрос для выполнения двух функций? Как создать класс php для действий навигации unlink не работает с пробелом в пути к папке Получите данные на стене или стене группы facebook для использования на личном веб-сайте APN php code дает предупреждение: stream_socket_client () : невозможно подключиться к ssl: //gateway.sandbox.push.apple.com: 2195 Закрытие не может быть сериализовано, как делать обратные вызовы через AJAX на PHP? Изменить «HUE» изображения с помощью библиотеки PHP GD?

PHP: проверить строку для определенных слов

Как я могу проверить, есть ли в нем данные, представленные в форме или querystring, определенные слова?

Я пытаюсь найти слова, содержащие admin, drop, create и т. Д. В форме [Post] data и querystring data, чтобы я мог принять или отклонить его.

Я перехожу от ASP к PHP. Я использовал это, используя массив в ASP (сохраняйте все незаконные слова в строке и используйте ubound для проверки всей строки для этих слов), но есть ли лучший (эффективный) способ сделать это в PHP?

Например: строка, подобная этой, будет отвергнута: «Администратор сбросил бла-бла», потому что у него есть админ и он заходит.

Я намерен использовать это, чтобы проверять имена пользователей при создании учетных записей и для других вещей.

благодаря

Solutions Collecting From Web of "PHP: проверить строку для определенных слов"

Вы можете использовать stripos()

 int stripos ( string $haystack , string $needle [, int $offset = 0 ] ) 

У вас может быть такая функция, как:

 function checkBadWords($str, $badwords) { foreach ($badwords as $word) { if (stripos(" $str ", " $word ") !== false) { return false; } } return true; } 

И использовать его:

 if (!checkBadWords('something admin', array('admin')) { // ... } 

strpos () позволит вам искать подстроку в большей строке. Это быстро и хорошо работает. Он возвращает false, если строка не найдена, и число (которое может быть нулевым, поэтому вам нужно использовать === для проверки), если он найдет строку.

stripos () является нечувствительной к регистру версией того же самого.

Я пытаюсь найти слова, содержащие admin, drop, create и т. Д. В форме [Post] data и querystring data, чтобы я мог принять или отклонить его.

Я подозреваю, что вы пытаетесь отфильтровать строку, поэтому она подходит для включения в нечто вроде запроса к базе данных или что-то в этом роде. Если это так, это, вероятно, не очень хороший способ сделать это, и вам действительно нужно будет избежать строки, используя mysql_real_escape_string () или эквивалент.

 $badwords = array("admin", "drop",); foreach (str_word_count($string, 1) as $word) { foreach ($badwords as $bw) { if (strpos($word, $bw) === 0) { //contains word $word that starts with bad word $bw } } } 

Для JGB146 приведено сравнение производительности с регулярными выражениями:

 <?php function has_bad_words($badwords, $string) { foreach (str_word_count($string, 1) as $word) { foreach ($badwords as $bw) { if (stripos($word, $bw) === 0) { return true; } } return false; } } function has_bad_words2($badwords, $string) { $regex = array_map(function ($w) { return "(?:\\b". preg_quote($w, "/") . ")"; }, $badwords); $regex = "/" . implode("|", $regex) . "/"; return preg_match($regex, $string) != 0; } $badwords = array("abc", "def", "ghi", "jkl", "mnop"); $string = "The quick brown fox jumps over the lazy dog"; $start = microtime(true); for ($i = 0; $i < 10000; $i++) { has_bad_words($badwords, $string); } echo "elapsed: ". (microtime(true) - $start); $start = microtime(true); for ($i = 0; $i < 10000; $i++) { has_bad_words2($badwords, $string); } echo "elapsed: ". (microtime(true) - $start); 

Пример вывода:

 Истек: 0.076514959335327
 Истек: 0,29999899864197

Поэтому регулярные выражения намного медленнее.

Вы можете использовать регулярное выражение следующим образом:

 preg_match("~(admin)|(drop)|(another token)|(yet another)~",$subject); 

построение строки шаблона из массива

 $pattern = implode(")|(", $banned_words); $pattern = "~(".$pattern.")~"; 
 function check($string, $array) { foreach($array as $item) { if( preg_match("/($item)/", $string) ) return true; } return false; } 

Вы, конечно, можете сделать цикл, как предложили другие. Но я думаю, что вы можете приблизиться к поведению, которое вы ищете, с операцией, которая непосредственно использует массивы, плюс позволяет выполнять выполнение с помощью одного оператора if .

Первоначально я думал, что вы можете сделать это с помощью простого вызова preg_match() (следовательно, downvote), однако preg_match не поддерживает массивы. Вместо этого вы можете выполнить замену через preg_replace чтобы все отвергнутые строки были заменены ничем, а затем проверьте, не изменилась ли строка. Это просто и позволяет избежать итерации цикла для каждой отклоненной строки.

 $rejectedStrs = array("/admin/", "/drop/", "/create/"); if($input == preg_replace($rejectedStrs, "", $input)) { //do stuff } else { //reject } 

Также обратите внимание, что вы можете обеспечить поиск без учета регистра, используя флаг i в шаблонах регулярных выражений, изменяя массив шаблонов на $rejectedStrs = array("/admin/i", "/drop/i", "/create/i");

Эффективность

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

 $input = "You can certainly do a loop, as others have suggested. But I think you can get closer to the behavior you're looking for with an operation that directly uses arrays, plus it allows execution via a single if statement. You can certainly do a loop, as others have suggested. But I think you can get closer to the behavior you're looking for with an operation that directly uses arrays, plus it allows execution via a single if statement."; $input = "Short string with no matches"; $input2 = "Longer string with a lot more words but still no matches. Longer string with a lot more words but still no matches. Longer string with a lot more words but still no matches. Longer string with a lot more words but still no matches. Longer string with a lot more words but still no matches. Longer string with a lot more words but still no matches. Longer string with a lot more words but still no matches. "; $input3 = "Short string which loop will match quickly"; $input4 = "Longer string that will eventually be matches but first has a lot of words, followed by more words and then more words, followed by more words and then more words, followed by more words and then more words, followed by more words and then more words, followed by more words and then more words, followed by more words and then more words, followed by more words and then more words, followed by more words and then more words and then finally the word create near the end"; $start1 = microtime(true); $rejectedStrs = array("/loop/", "/operation/", "/create/"); $p_matches = 0; for ($i = 0; $i < 10000; $i++) { if (preg_check($rejectedStrs, $input)) $p_matches++; if (preg_check($rejectedStrs, $input2)) $p_matches++; if (preg_check($rejectedStrs, $input3)) $p_matches++; if (preg_check($rejectedStrs, $input4)) $p_matches++; } $start2 = microtime(true); $rejectedStrs = array("loop", "operation", "create"); $l_matches = 0; for ($i = 0; $i < 10000; $i++) { if (loop_check($rejectedStrs, $input)) $l_matches++; if (loop_check($rejectedStrs, $input2)) $l_matches++; if (loop_check($rejectedStrs, $input3)) $l_matches++; if (loop_check($rejectedStrs, $input4)) $l_matches++; } $end = microtime(true); echo "preg_match: ".$start1." ".$start2."= ".($start2-$start1)."\nloop_match: ".$start2." ".$end."=".($end-$start2); function preg_check($rejectedStrs, $input) { if($input == preg_replace($rejectedStrs, "", $input)) return true; return false; } function loop_check($badwords, $string) { foreach (str_word_count($string, 1) as $word) { foreach ($badwords as $bw) { if (stripos($word, $bw) === 0) { return true; } } return false; } } 

Вывод:

preg_match: 1281908071.4032 1281908071.9947 = 0.5915060043335

loop_match: 1281908071.9947 1281908073.006 = 1.0112948417664

Это на самом деле довольно просто, используйте substr_count.

И примером для вас было бы:

 if (substr_count($variable_to_search, "drop")) { echo "error"; } 

И чтобы сделать вещи еще проще, поместите свои ключевые слова (например, «drop», «create», «alter») в массив и используйте foreach для их проверки. Таким образом, вы покрываете все свои слова. Пример

 foreach ($keywordArray as $keyword) { if (substr_count($variable_to_search, $keyword)) { echo "error"; //or do whatever you want to do went you find something you don't like } }