Невозможно удалить тире (-) из строки

Следующая функция разделяет некоторые слова на массив, корректирует пробелы и делает что-то еще, что мне нужно. Мне также нужно убрать тире, так как я тоже пишу их как слова. Но эта функция не удаляет тире. Что случилось?

function stripwords($string) 
{ 
  // build pattern once 
  static $pattern = null; 
  if ($pattern === null) { 
    // pull words to remove from somewhere 
    $words = array('alpha', 'beta', '-');  
    // escape special characters 
    foreach ($words as &$word) { 
      $word = preg_quote($word, '#'); 
    } 
    // combine to regex 
    $pattern = '#\b(' . join('|', $words) . ')\b\s*#iS'; 
  } 

  $print = preg_replace($pattern, '', $string);
  list($firstpart)=explode('+', $print);
  return $firstpart;

}

person smepie    schedule 05.07.2011    source источник
comment
Как выглядит $pattern?   -  person Ignacio Vazquez-Abrams    schedule 05.07.2011
comment
Это растяжка, а не тире. Даш это: —   -  person Buddy    schedule 05.07.2011
comment
Можете ли вы привести пример, который не работает должным образом?   -  person Gumbo    schedule 05.07.2011
comment
@Buddy ES80 - это не тире? во всяком случае, я пробовал с hypen и тире, и это не удаляет ...   -  person smepie    schedule 05.07.2011


Ответы (2)


Чтобы ответить на ваш вопрос, проблема заключается в том, что \b обозначает границу слова. Если у вас есть пробел до или после дефиса, он не удалит его, как в «-», граница слова не применяется.

Из http://www.regular-expressions.info/wordboundaries.html:

Есть три разных положения, которые можно квалифицировать как границы слов:

  1. Перед первым символом в строке, если первый символ является символом слова.
  2. После последнего символа в строке, если последний символ является символом слова.
  3. Между двумя символами в строке, где один является символом слова, а другой не является символом слова.

«Словарный символ» — это символ, который можно использовать для образования слов.

Простое решение:

Добавив \s вместе с \b к вашему шаблону и используя положительный взгляд назад и положительный взгляд вперед, вы сможете решить свою проблему.

$pattern = '#(?<=\b|\s|\A)(' . join('|', $words) . ')(?=\b|\s|\Z)\s*#iS'; 
person Francois Deschenes    schedule 05.07.2011
comment
а как быть с пробелами и составными словами? то есть ... мне нужно, чтобы альфа была удалена, когда это только одно слово ... а не альфа в алфавите (составное слово, например) - person smepie; 05.07.2011
comment
@smepie - я обновил приведенное выше регулярное выражение, чтобы использовать положительный просмотр вперед и положительный просмотр назад для поиска границы слова и пробела. Это также не идеально, так как оно не удалит тире, если это последний символ или если слово начинается или заканчивается тире. - person Francois Deschenes; 05.07.2011
comment
с вашим шаблоном CANON DIGITAL становится CNONgitl и SAMSUNG -> SMSUNG, так что, возможно, это означает, что он конфликтует с другими словами в массиве... - person smepie; 05.07.2011
comment
@smepie - я не пробовал CANON DIGITAL и SAMSUNG, и они отлично работали. У вас должно быть что-то еще, зачищающее букву А. - person Francois Deschenes; 05.07.2011
comment
ну объясните лучше: каждое слово, которое я записываю в массив, оно должно удаляться. хорошо... но он должен удалить A только тогда, когда A один. Так понятно? - person smepie; 05.07.2011
comment
@smepie - Конечно. Но когда я попробовал это, используя приведенный выше код и добавив в список слов для удаления, CANON — это CANON, а не CNON. Убедитесь сами: http://codepad.viper-7.com/UTv8Qb. - person Francois Deschenes; 05.07.2011
comment
извините... это была ранняя версия, теперь вроде работает, но странное поведение: слово nero является одним из слов в массиве, теперь он удаляет тире, но не nero.... как это возможно? - person smepie; 05.07.2011
comment
ES80 - NERO... стрижет - но не NERO - person smepie; 05.07.2011
comment
@smepie - я снова обновил шаблон. Я думаю, что это должно решить все ваши проблемы. Он также использует \A и \Z, чтобы позаботиться о дефисах, которые также начинают или заканчивают строку. - person Francois Deschenes; 05.07.2011
comment
ОК, мы близки к решению :-), но для альфа-бета ничего не нужно удалять, если я не записываю альфа-бета точно в массив... - person smepie; 05.07.2011
comment
@smepie - В этом случае вам придется избавиться от \b, так как в альфа-бета есть граница слова, где дефис. Используйте $pattern = '#(?<=\s|\A)(' . join('|', $words) . ')(?=\s|\Z)\s*#iS';. - person Francois Deschenes; 05.07.2011

Нигде в шаблоне регулярного выражения вы не ищете тире. Почему бы просто не сделать

$string = str_replace('-', '', $string);

после того, как вы сделаете свои регулярные выражения?

person Marc B    schedule 05.07.2011