2013-09-12 4 views
0

Поскольку я не могу использовать preg_match (поддержка UTF8 как-то сломана, она работает локально, но ломается при производстве). Я хочу найти другой способ совпадения слова с черным списком. Проблема в том, что я хочу искать строку только для точного соответствия, а не для первого появления строки.матч всего слова только без регулярного выражения

Это, как я делаю это с preg_match

preg_match('/\b(badword)\b/', strtolower($string)); 

Пример строки:

$string = "This is a string containing badwords and one badword"; 

Я хочу только соответствовать "BADWORD" (в конце), а не "BADWORDS".

strpos('badword', $string) matches the first one 

Любые идеи?

+0

Разделить строку на пробелы и проверить каждое слово против вашего черного списка – jonhopkins

+0

@jonhopkins Это не будет работать для пунктуации (предполагая, что будут какие-то). –

+0

Правда .. Не думал об этом. Конечно, есть способ препинания пунктуации? – jonhopkins

ответ

1

Предполагая, что вы могли бы сделать некоторые предварительной обработки, вы можете использовать заменить все знаки препинания с пробелами и поместить все в нижнем регистре, а затем либо:

  • Используйте strpos с чем-то вроде так strpos(' badword ', $string) в цикле в то время как продолжать повторять весь ваш документ;
  • Разделите строку в белых местах и ​​сравните каждое слово со списком плохих слов, которые у вас есть.

Так что, если вы где попробовав первый вариант, это будет что-то вроде так (непроверенного псевдокода)

$documet = body of text to process . ' ' 
$document.replace('[email protected]#$%^&*(),./...', ' ') 
$document.toLowerCase() 
$arr_badWords = [...] 
foreach($word in badwords) 
{ 
    $badwordIndex = strpos(' ' . $word . ' ', $document) 
    while(!badWordIndex) 
    { 
     // 
     $badwordIndex = strpos($word, $document) 
    } 
} 

EDIT: По предложению @jonhopkins, добавив белое пространство в конце должны обслуживать сценарий, в котором требуется слово, находится в конце документа и не проходит знак препинания.

+1

Что делать, если плохое слово является самым первым словом в документе или последним словом и после него не было никаких знаков препинания? Я не думаю, что это соответствовало бы этому. Но было бы приемлемо добавить пространство в начало и конец '$ document', чтобы быть уверенным? – jonhopkins

+0

@ jonhopkins: Согласен. Поправил ответ в соответствии с вашим предложением. – npinti

0

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

strrpos - Находит позицию последнего вхождения подстроки в строке

$string = "This is a string containing badwords and one badword"; 
var_dump(strrpos($string, 'badword')); 

Выход:

45 
+1

Это предполагает, что строка известна программисту. Если строка извлекается из пользовательского ввода, возможно, что вложенное в черный список слово может прийти перед другим словом, которое будет сопоставлено, поэтому это не обязательно работает ни на чем, кроме тестового примера выше. – jonhopkins

0

Простой способ использования границ слов с помощью unicode Свойства:

preg_match('/(?:^|[^pL\pN_])(badword)(?:[^pL\pN_]|$)/u', $string); 

На самом деле это гораздо сложнее, взглянуть на here.

1

Если вы хотите, чтобы имитировать \b модификатор регулярных выражений вы можете попробовать что-то вроде этого:

$offset = 0; 
$word = 'badword'; 
$matched = array(); 
while(($pos = strpos($string, $word, $offset)) !== false) { 
    $leftBoundary = false; 
    // If is the first char, it has a boundary on the right 
    if ($pos === 0) { 
     $leftBoundary = true; 
    // Else, if it is on the middle of the string, we must check the previous char 
    } elseif ($pos > 0 && in_array($string[$pos-1], array(' ', '-',...)) { 
     $leftBoundary = true; 
    } 

    $rightBoundary = false; 
    // If is the last char, it has a boundary on the right 
    if ($pos === (strlen($string) - 1)) { 
     $rightBoundary = true; 
    // Else, if it is on the middle of the string, we must check the next char 
    } elseif ($pos < (strlen($string) - 1) && in_array($string[$pos+1], array(' ', '-',...)) { 
     $rightBoundary = true; 
    } 

    // If it has both boundaries, we add the index to the matched ones... 
    if ($leftBoundary && $rightBoundary) { 
     $matched[] = $pos; 
    } 

    $offset = $pos + strlen($word); 
} 
Смежные вопросы