У меня есть код,

$text = "This is a $1ut ( Y ) @ss @sshole a$$ ass test with grass and passages.";
$blacklist = array(
  '$1ut',
  '( Y )',
  '@ss',
  '@sshole',
  'a$$',
  'ass'
);
foreach ($blacklist as $word) {
  $pattern = "/\b". preg_quote($word) ."\b/i";
  $replace = str_repeat('*', strlen($word));
  $text = preg_replace($pattern, $replace, $text);
}
print_r($text);

Которые возвращают следующий результат:

This is a $1ut ( Y ) @ss @sshole a$$ *** test with grass and passages.

Когда я удаляю границу слова из регулярного выражения,

$pattern = "/". preg_quote($word) ."/i";

Он возвращается:

This is a **** ***** *** ***hole *** *** test with gr*** and p***ages.

Как я могу написать регулярное выражение, чтобы оно не заменяло такие слова, как passages, grass и т. Д., А полностью заменяло, например, @sshole?

0
Vlad Stratulat 26 Сен 2012 в 17:03
5
Следует добавить, что независимо от того, насколько вы думаете, что список слов с ругательствами и заменой w поможет, люди всегда будут пытаться найти его вокруг, и в конечном итоге они это сделают. Тогда это было бы просто мудаком или дырой в $$.
 – 
h2ooooooo
26 Сен 2012 в 17:05
Да, я знаю это. Из-за этого список слов будет расти. Но мой вопрос в том, как написать регулярное выражение. Это можно использовать не только для предотвращения бранных слов, но и в любых подобных ситуациях.
 – 
Vlad Stratulat
26 Сен 2012 в 17:08
1
Я думаю, что более важный вопрос - почему с \ b не удается найти ваши слова
 – 
BugFinder
26 Сен 2012 в 17:12
2
Кажется, что большинство систем регулярных выражений не могут обрабатывать \b@ss\b, но могут легко обрабатывать \bass\b. Странный. Изменить Очевидно \b поддерживает только ASCII: stackoverflow.com/questions/2881445/…
 – 
h2ooooooo
26 Сен 2012 в 17:13

1 ответ

Лучший ответ

Согласно это \b не поддерживает ничего, кроме [A-Za-z0-9_].

Обратите внимание, что вам нужно экранировать свое регулярное выражение, поскольку вы генерируете его из строки (а компилятор PHP в момент создания этой строки не знает, что это регулярное выражение).

Использование Regex /(^|\s)WORD($|\s)/i, похоже, работает.

Пример кода:

$text = "This is a $1ut ( Y ) @ss @sshole a$$ ass test with grass and passages.";
$blacklist = array(
  '$1ut',
  '( Y )',
  '@ss',
  '@sshole',
  'a$$',
  'ass'
);
foreach ($blacklist as $word) {
  $pattern = "/(^|\\s)" . preg_quote($word) . "($|\\s)/i";
  $replace = " " . str_repeat('*', strlen($word)) . " ";
  $text = preg_replace($pattern, $replace, $text);
}
echo $text;

Выход:

This is a **** ***** *** ******* *** *** test with grass and passages.

Имейте в виду, что если ваша строка начинается или заканчивается одним из этих слов, мы добавим пробел к совпадению на каждом конце, что означает, что перед текстом или после текста будет пробел. Вы можете позаботиться об этом с помощью trim()

Обновление;

Также имейте в виду, что это никоим образом не учитывает пунктуацию.

the other user has an ass. and it is nice, например, пройдет.

Чтобы победить это, вы можете расширить его еще больше:

/(^|\\s|!|,|\.|;|:|\-|_|\?)WORD($|\\s|!|,|\.|;|:|\-|_|\?)/i

Это означало бы, что вам также пришлось изменить способ, которым мы заменяем:

$text = "This is a $1ut ( Y ) @ss?@sshole you're an ass. a$$ ass test with grass and passages.";
$blacklist = array(
  '$1ut',
  '( Y )',
  '@ss',
  '@sshole',
  'a$$',
  'ass'
);
foreach ($blacklist as $word) {
  $pattern = "/(^|\\s|!|,|\\.|;|:|\\-|_|\\?)" . preg_quote($word) . "($|\\s|!|,|\\.|;|:|\\-|_|\\?)/i";
  $replace = '$1' . str_repeat('*', strlen($word)) . '$2';
  $text = preg_replace($pattern, $replace, $text);
}
echo $text;

И добавьте все остальные знаки препинания и т. д.

Выход:

This is a **** ***** ***?******* you're an ***. *** *** test with grass and passages.

3
Community 23 Май 2017 в 14:48
Спасибо h2ooooooo! Я попробую и скоро вернусь.
 – 
Vlad Stratulat
26 Сен 2012 в 17:31