Как удалить (большинство) коротких слов из строки

#php #regex

#php #регулярное выражение

Вопрос:

В настоящее время я использую следующее регулярное выражение для удаления маленьких слов (< 4 символов) из строки.

 $dirty = "I welcome you to San Diego";
$clean = preg_replace("/b[^s]{1,3}b/", "", $dirty);
  

Итак, это привело бы к «Добро пожаловать, Диего»;

Однако теперь мне нужно игнорировать замену определенных слов, например:

 $ignore = array("San", "you");
  

в результате получилось бы «добро пожаловать в Сан-Диего»

Комментарии:

1. Большинство поисковых систем справляются с этим, указывая черный список «стоп-слов». armandbrahaj.blog.al/2009/04/14/list-of-english-stop-words

2. Что [^s] используется для вместо S ? Кроме того, вы понимаете, что b это определяется не в терминах S -vs- s , а скорее в терминах w только?

Ответ №1:

Вы можете встроить свой список игнорирования, используя (?!..) отрицательное утверждение:

  preg_replace("/b(?!San|you|not)w{1,3}b/", "", ...
  

Также я бы просто использовал w вместо [^s] , чтобы это действительно соответствовало только словам.

Комментарии:

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

2. @Frits: Здесь также проще встроить | сжатый список слов. Но, тем не менее, я также поддержал альтернативу обратного вызова;} хотя бы потому, что я думаю, что preg_replace_callback упоминается слишком редко.

3. @Frits: Действительно, единственным «недостатком» является то, что вы должны прогнать список слов через preg_quote , прежде чем распадаться на | , но это также можно сделать в одной строке с array_map , так что это не имеет большого значения. Не знаю, почему этот ответ не был принят вместо этого.

Ответ №2:

Я рекомендую использовать обратный вызов (preg_replace_callback), поскольку это обеспечивает более удобное решение, если вам нужно масштабировать до большого количества слов:

 echo preg_replace_callback(
    '/b[^s]{1,3}b/',
    create_function(
        '$matches',
        '$ignore = array("San", "you");
         if (in_array($matches[0], $ignore)) {
            return $matches[0];
         } else {
            return '';
         }'
    ),
    "I welcome you to San Diego"
); 
// output: welcome you San Diego 
  

Если вы используете PHP 5.3 или более поздней версии, вы могли бы использовать анонимную функцию вместо вызова create_function.

Комментарии:

1. Имейте в виду, что create_function вызывает известную утечку памяти. Лучше избегать этого.

2. Я думаю, вы хотите bw{1,3}b туда.