Вырезать слова не нужной длины (preg_replace)

  • Автор темы Леша Темный
  • Дата начала

Леша Темный

Guest
Вырезать слова не нужной длины (preg_replace)

Нужно вырезать из строки все слова короче M букв и длинее N букв
Делаю так
PHP:
preg_replace('#\s(\S{1,2}|\S{5,})\s#', ' ', "sh shot \n longlong sh longlonglong")
, но это регулярное выражение выдает
PHP:
"sh shot \n sh longlonglong"
Что я делаю не правильно? (PHP - Win32)
 

uchenik

Новичок
распиши словами, что делает твой шаблон

-~{}~ 09.04.05 23:40:

и поймешь почему не совпадают некоторые слова.
 

Леша Темный

Guest
Приведенный шаблон соответвует всем словам состящих из одного или двух непробельных символов \S{1,2} и словам с длиной 5 или более \S{5,}
Слово это последовательность непробельных символов ограниченных пробельными \s

! К стате в phpBB2 подобная операция реализована следующим образом
PHP:
$entry = preg_replace('/[ ]([\S]{1,2}|[\S]{21,})[ ]/',' ', $entry);
и дает похожие результаты:
PHP:
"sh shot \n longlong longlonglong"
Как видите он пропускает некоторые слова длиной 2 символа и слова более 5 или символов.

Может я не правльно трактую {1,2} и {5,} ?

-~{}~ 10.04.05 09:09:

А х, да согласен, привел не очень хороший пример.
Не хотел длинный пример показывать, но похоже прийдется - исходний пример у меня очень длинный приведу лишь выдержку
PHP:
preg_replace('#\s(\S{1,2}|\S{5,})\s#', ' ', " Гостевая книга gbook 0 Описание моего скрипта гостевой книги gbook 0 \n Обсудить на форуме ");
После обработки
PHP:
" книга 0 моего гостевой gbook \n на "
 

uchenik

Новичок
Из твоих же слов следует, что слова должны ограничиватся С ДВУХ СТОРОН пробелами. Под эту формулировку написан и шаблон.

Но в строке "sh shot \n longlong longlonglong" есть два слова, которые ограничены пробелом лишь с одной стороны - это "sh" и "longlonglong". Эти слова не соответсвуют твоему шаблону, поэтому не производится замена.

Чтобы регулярка работала правильно слова необходимо ограничивать не пробелами, а границами слова - "\b".

PHP:
preg_replace('/\b(\S{1,2}|\S{5,})\b/', "",  $text)
И вырезаемое слово лучше менять на пустую строку "", а не пробел, тогда слово действительно будет "вырезатся".

-~{}~ 10.04.05 11:48:

Границы слова "\b" совпадают не с символами, а с позициями.
 

Леша Темный

Guest
Спасибо, так работает.

Но меня интресует почему были пропущены слова и в середине текста, как во втором примере (заметь с права и слева ДОБАВЛЕНЫ пробелы), так что условие должно выполниться ???

А почему не работает первый приведенный мною пример я и сам понял.
 

sakon

П..и.н..ок
меня интресует почему были пропущены слова и в середине текста, как во втором примере (заметь с права и слева ДОБАВЛЕНЫ пробелы), так что условие должно выполниться ???
Помоему uchenik тебе конкретно ответил совпадают не с символами, а с позициями.

Для проверки добавь к каждому пробелу еще по одному пробелу и посмотри на резултат.;)

-~{}~ 10.04.05 16:59:

Леша Темный
твой рег надо было записать так:
PHP:
'/(?<=\s)(\S{1,2}|\S{5,})(?=\s)/'
но у uchenik он короче.
 

uchenik

Новичок
PHP:
setlocale(LC_ALL,"rus");
preg_replace('/\b([а-яё\w]{1,2}|[а-яё\w]{5,})\b/i', '', $text);
Если тебе нужно работать с русскими буквами, то используй в шаблоне не "\S", а символьные классы.
 

sakon

П..и.н..ок
uchenik
У него в приведенной строке присутствует и латиница и цифры. Так, что использование '\S' оправдано. Иначе придется писать длинный символьный класс.
С другой стороны его рег вполне пропустит '/// .... ... .... *** \\\'
 

Леша Темный

Guest
Автор оригинала: sakon
С другой стороны его рег вполне пропустит '/// .... ... .... *** \\\'
Пропустит, но они не попадуться: все что заранее не нужно вырзается раньше, а в остальном может быть что угодно.

В общем я так и не понял, почему не работает мой рег, но все равно спасибо вариант uchenik хорошо работает.
 

sakon

П..и.н..ок
>В общем я так и не понял, почему не работает мой рег

Это плохо..
 

Леша Темный

Guest
Сново трабл. Дома (PHP5 Win32) работает, а вот на хостинге (PHP4, FreeBSD) не работает :( некоторые пропускает (и короткие и длинные).
 

sakon

П..и.н..ок
Попробую объяснить на примере твоей строки и твоего рега:
строка - ' Гостевая книга gbook 0 Описание моего скрипта гостевой книги gbook 0 \n Обсудить на форуме '
рег - '/\s(\S{1,2}|\S{5,})\s/'

Рег начинает проверку:| Гостевая | - сначала побел (ОК), дальше 1 или 2 или 5 и болше символов (OK), после чего идет пробел (ОК) - данная последовательность подошла под рег. выражение и была заменена (preg_replace).
Слово |книга| - сначала побел (NO потому, что пробел перед словом вошел в предыдущую маску и позиция с которой началась проверка соответствует символу к, а не пробелу как ты ожидаешь).
Таким образом происходит проверка, пока вновь не встретится пробел, перевод строки, табуляция и т.д.

-~{}~ 10.04.05 18:12:

Леша Темный
>на хостинге (PHP4, FreeBSD) не работает
А ты правильно его туда скопировал?
 

Леша Темный

Guest
Большое спасибо, теперь ясно.

Насчет проблемы:

Вариант
PHP:
'/\b(\S{1,2}|\S{5,})\b/'
работает дома, но не работает на хостинге ( http://zolotov.h14.ru/phpinfo.php (времено выложил) )

Вариант
PHP:
'/(?<=\s)(\S{1,2}|\S{5,})(?=\s)/'
работает и там и там (кажется)

Так вот вопрос: будет ли второй вариант работать везде? Или тоже возможны варианты.

PS Что-то у меня уже больше желание решить проблему без регулярки (может и медление, но надежнее)
 

sakon

П..и.н..ок
>будет ли второй вариант работать везде?
Должен, в принципе как и тот, что предложил uchenik

>Что-то у меня уже больше желание решить проблему без регулярки
Неправильное желание.... (IMHO)
 

uchenik

Новичок
PHP:
'/(?<=\s)(\S{1,2}|\S{5,})(?=\s)/'
данный шаблон требует пробелов с обеих сторон.

Он не будет работать в такой строке "sh shot \n sh longlonglong".
 

Леша Темный

Guest
uchenik
>'/(?<=\s)(\S{1,2}|\S{5,})(?=\s)/'
>данный шаблон требует пробелов с обеих сторон

Это я уже тоже заметил.

ну что, асы подскажите какой код надо использовать, чтобы работало везде.
 

uchenik

Новичок
Если ты писал на хостинге
PHP:
setlocale(LC_ALL,"rus");
, но регулярка не работала, то это значит что проблемы с локалью.

Решается она просто небольшим удлинением шаблона:

PHP:
preg_replace('/\b([\wа-яА-ЯЁё]{1,2}|[\wа-яА-ЯЁё]{5,})\b/i', '', $text);

:) :)

какая-то херомантия при копировании вылезла.

-~{}~ 10.04.05 17:37:

будет работать везде.
 

sakon

П..и.н..ок
uchenik
'/\b(\S{1,2}|\S{5,})\b/' тоже должен работать. Что нить не так скопировал. Скорее всего где-то вкрался пробел......
 
Сверху