Модераторы: Aliance, skyboy, MoLeX, ksnk

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [RegEx]извлечение слов из строки, с (вложенными)кавычками 
V
    Опции темы
Splendid
Дата 19.11.2007, 11:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 256
Регистрация: 1.8.2007
Где: Беларусь, Минск

Репутация: нет
Всего: нет



Подскажите, пожалуйста, как изменить это регулярное выражение?
сейчас оно разбивает строку на слова: 
1. перед которыми стоит минус
2. перед которыми стоит плюс
3. те, что заключены в кавычки "слово слово2"

и фразу "Закон Республики Беларусь "О печати"" оно сейчас разбивает на:
1. Закон Республики Беларусь
2. о
3. печати

Ну а надо, чтобы разбивало так: 
1. Закон Республики Беларусь "О печати".

Вот...помогите, пожалуйста...

Код

   $pattern = '/(?(?=\")\"([^\"]+)\"|(\+|-)?(\b\w+\b))/iUs';



 


PM MAIL   Вверх
kasmanaft
Дата 19.11.2007, 12:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 94
Регистрация: 16.11.2007

Репутация: 1
Всего: 2



Здесь можно зацепиться за "" - две рядомстоящие кавычки.

Попробуйте так:
$pattern = '/(?(?=\")\".*\"(?![^\"]*\"\")|(\+|-)?(\b\w+\b))/iUs';

PS из-за этого, может быть, глючить будет в каких-нибудь хитрых местах.
PM MAIL   Вверх
Splendid
Дата 19.11.2007, 14:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 256
Регистрация: 1.8.2007
Где: Беларусь, Минск

Репутация: нет
Всего: нет



kasmanaft, спасибо!
Но это ведь частный случай - две рядом стоящие кавычки...
здесь скорее как-то надо типа с первой кавычки по последнюю кавычку...просто я в регулярках не сильна, поэтому и спрашиваю
PM MAIL   Вверх
kasmanaft
Дата 19.11.2007, 15:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 94
Регистрация: 16.11.2007

Репутация: 1
Всего: 2



" издали " закон " о печати " блаблабла " " - вот попробуйте определить, что я здесь взял в кавычки smile 

По идее хотел вот так: "издали "закон "о печати" блаблабла""

 . . . . 

 smile О да!.. кой-чего пришло: перез закрывающей кавычкой не должно стоять пробела. А число закрывающих должно соответствовать числу уже открытых. Как бы это записать теперь smile


PM MAIL   Вверх
Splendid
Дата 19.11.2007, 15:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 256
Регистрация: 1.8.2007
Где: Беларусь, Минск

Репутация: нет
Всего: нет



kasmanaftsmile) вопрос интересныйsmile

у меня с этой регуляркой еще одна проблема возникла, при переносе на сервер она странно разбивает слова, например экран ищет как 2 слова: "к" и "ан", в чем здесь может быть проблема???

в некоторых словах обрезает последнюю букву, а некоторые нормально ищет...
PM MAIL   Вверх
kasmanaft
Дата 19.11.2007, 15:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 94
Регистрация: 16.11.2007

Репутация: 1
Всего: 2



Я сейчас подумаю как записать то, что напридумывал.. А ты покажи пока код свой. А то в зависимости от того какой функцией разбиваешь, разные проблемы могут быть..

И скорее всего предыдущую рег. экспу придется разбить на две... Потому что получится слишком заумно (а она и так, надо сказать, непростая)
PM MAIL   Вверх
Splendid
Дата 19.11.2007, 15:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 256
Регистрация: 1.8.2007
Где: Беларусь, Минск

Репутация: нет
Всего: нет



вот код:
Код

function prepareWhere($search, $fields)
{
    if ($search!=''){
    // Разбираем строку на слова
    $reg = '/(?(?=")"([^"]+)"|(\+|-)?(\b\w+\b))/iUs';
   preg_match_all($reg, $search, $words, PREG_PATTERN_ORDER);
    
    $words_groups = array();
    $words_groups['include']=array();
    $words_groups['exclude']=array();
    $words_groups['any']=array();
    
    // Каждое слово обрабатываем, определяем его тип
    foreach( $words[0] as $word )
    {
        $word = trim($word); // Удаляем лишние пробелы
        if( strlen($word) > 0 ) // Если слово не пустое, то продалжаем с ним
        {
            $word = mysql_real_escape_string($word);
            $word = addCslashes($word, '_%');
            switch( $word[0] )
            {
                case '+': // Обязательные слова
                    $words_groups['include'][] = substr($word, 1);
                    break;
                case '-': // Ненужные слова
                    $words_groups['exclude'][] = substr($word, 1);
                    break;
                default: // Наличие хотя бы одного слова
                    $word = str_replace(array('\\','"'), '', $word);
                    $words_groups['any'][] = $word;  
            }
        }
    }
    
    // "Группируем" группы слов, учитывая поля 
    $words_rules = array();
    $words_rules['include']=array();
    $words_rules['exclude']=array();
    $words_rules['any']=array();
    
    foreach( $fields as $field )
    {
        // Ненужные слова
        if( count($words_groups['exclude']) > 0 )
        
        $words_rules['exclude'][] = ' ('.$field.' NOT LIKE "%'. implode('%" AND '.$field.' NOT LIKE "%', $words_groups['exclude']) .'%" OR '.$field.' is null) ';
        
        // Наличие хотя бы одного слова            
        if( count($words_groups['any']) > 0 )

            $words_rules['any'][] = ' ('.$field.' LIKE "%'. implode('%" OR '.$field.' LIKE "%', $words_groups['any']) .'%") ';
    }
    
        if( count($words_groups['include']) > 0 ) 
        foreach( $words_groups['include'] as $word )
 
            $words_rules['include'][] = ' ('.implode(' LIKE "%'.$word.'%" OR ', $fields).' LIKE "%'.$word.'%") ';
            
    
    // Объединяем результаты
    if( count($words_rules['include']) > 0 )
        $where['include'] = '('.implode(' AND ', $words_rules['include']).')';
    if( count($words_rules['exclude']) > 0 )
        $where['exclude'] = '('.implode(' AND ', $words_rules['exclude']).')'; 
    if( count($words_rules['any']) > 0 )
        $where['any'] = '('.implode(' OR ', $words_rules['any']).')';
   
 $where = implode(' AND ', $where);
    return $where;
    }
}
;
$where = prepareWhere($search, $table_columns_exp);


Добавлено через 30 секунд
причем локально все работает правильно
PM MAIL   Вверх
kasmanaft
Дата 19.11.2007, 16:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 94
Регистрация: 16.11.2007

Репутация: 1
Всего: 2



Ну начнем...

Придумал вот что: /"(?=\S)(?:[^"]*|(?R))*(?<=\S)"/is
Второе выражение, наверное, нужно вот таким оставить: (\+|-)(\b\w+\b) - убрал "+" после первой скобки, по-моему, он там не нужен. (объединить два выражения уже не получится, в первом использована рекурсия).

Итого тебе осталось два раза использовать preg_match_all() и после этого объединить полученные массивы (третий аргумент).

Проблемы на сервере могут быть из-за неправильно настроенной локали. Посмотри setlocale().
Может быть получится вот так setlocale (LC_ALL, array ('ru_RU.CP1251', 'rus_RUS.1251')), а может быть придется имена локалей уточнить у хостера.

Цитата
просто я в регулярках не _сильна_

Упс, а я и не приметил smile 
В таком случае, если чего не получится, помогу довести всё это дело до конца  smile  smile 

Это сообщение отредактировал(а) kasmanaft - 19.11.2007, 16:30
PM MAIL   Вверх
Splendid
Дата 19.11.2007, 16:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 256
Регистрация: 1.8.2007
Где: Беларусь, Минск

Репутация: нет
Всего: нет



Настройки локали у меня такие прописаны...но все равно глюки...

я уже вообще ничего не соображаю....
Помогите Ваши регулярки в мой код подставить, пожалуйста..
PM MAIL   Вверх
kasmanaft
Дата 19.11.2007, 17:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 94
Регистрация: 16.11.2007

Репутация: 1
Всего: 2



Цитата(Splendid @  19.11.2007,  16:38 Найти цитируемый пост)
Настройки локали у меня такие прописаны...но все равно глюки...
Попробуйте у хостера узнать их точное название.. По-моему, дело имеено в локали.

Что с кодом:
Поменяйте у себя
Код

    // Разбираем строку на слова
    $reg = '/(?(?=")"([^"]+)"|(\+|-)?(\b\w+\b))/iUs';
   preg_match_all($reg, $search, $words, PREG_PATTERN_ORDER);
на
Код

    // Разбираем строку на слова
    $reg = '/"(?=\S)(?:[^"]*|(?R))*(?<=\S)"/is';
    preg_match_all($reg, $search, $words1, PREG_PATTERN_ORDER);

    $reg = '/(?:\+|-)\b\w+\b/is';
    preg_match_all($reg, $search, $words2, PREG_PATTERN_ORDER);
    
    $words[0] = array_merge($words1[0], $words2[0]);

Потом надо что-то сделать с str_replace() вот здесь:
Код

                default: // Наличие хотя бы одного слова
                    $word = str_replace(array('\\','"'), '', $word);
                    $words_groups['any'][] = $word; 

Она не должна удалять кавычки внутри запроса, а только по краям (это можно решить с помощью trim($val, '"') ) и, наверное, не надо вообще удалять "\". (т.е. str_replace() заменить на trim() - вроде бы должно сработать)

Конечно же, нужно бы потестировать.

Это сообщение отредактировал(а) kasmanaft - 19.11.2007, 17:28
PM MAIL   Вверх
Splendid
Дата 19.11.2007, 17:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 256
Регистрация: 1.8.2007
Где: Беларусь, Минск

Репутация: нет
Всего: нет



Спасибо! Пойду пробовать!
а если такая локаль, то что прописывать надо: LANG = "ru_RU.UTF-8"????
PM MAIL   Вверх
kasmanaft
Дата 19.11.2007, 18:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 94
Регистрация: 16.11.2007

Репутация: 1
Всего: 2



Просто заменить те, что были наверху на эту. Но, честно говоря, не знаю, изменит ли это что-нибудь или нет - текст-то ведь в CP1215, а тут UTF-8.

Понял для чего нужен был тот вопросительный знак.. Всё-таки он был нужен.
То есть вот так попровте: $reg = '/(?:\+|-)?\b\w+\b/is';

И насчет локали.. Вы говорите, неправильно ищет слово "экран". А если его в кавычки взять? 
Если так сработает, то можно второе рег. выражение попробовать оформить вот так:
$reg = '/(?:\+|-)?\b[a-zA-Zа-яёА-ЯЁ0-9-_]+\b/is';
PM MAIL   Вверх
Splendid
Дата 19.11.2007, 18:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 256
Регистрация: 1.8.2007
Где: Беларусь, Минск

Репутация: нет
Всего: нет



в кавычках работает...


что же с этой локалью ничего сделать нельзя??? Может можно на серваке установить CP1215? Как вообще в этих случаях поступают?


если подставлять ваши 2 выражения - то выдает кучу ошибок...сейчас приведу их

Добавлено через 2 минуты и 12 секунд

Notice: Undefined variable: where in F:\Program Files\wamp\www\reestr_skript18\search.php on line 153

это отсюда

Код

  // Объединяем результаты
    if( count($words_rules['include']) > 0 )
        $where['include'] = '('.implode(' AND ', $words_rules['include']).')';
    if( count($words_rules['exclude']) > 0 )
        $where['exclude'] = '('.implode(' AND ', $words_rules['exclude']).')'; 
    if( count($words_rules['any']) > 0 )
        $where['any'] = '('.implode(' OR ', $words_rules['any']).')';
   
 $where = implode(' AND ', $where);
    return $where;
    }
}
;
$where = prepareWhere($search, $table_columns_exp);
$where1 = prepareWhere($search, $table_columns_sert);


надо видимо что-то еще в коде исравить
PM MAIL   Вверх
kasmanaft
Дата 19.11.2007, 18:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 94
Регистрация: 16.11.2007

Репутация: 1
Всего: 2



Цитата(Splendid @  19.11.2007,  18:12 Найти цитируемый пост)
если подставлять ваши 2 выражения - то выдает кучу ошибок...
Хм... странно.
Я забыл, что кавычки там будут экранированные, поэтому надо: trim($word, '\\"'). (кстати, Вы $val заменили на $word? я просто так, в качестве примера этот код привел..)

. . . . . .

Ага.. понял в чем дело (про trim() не забудте). Вы, видимо, не обратили внимание на вот это:
Цитата(kasmanaft @  19.11.2007,  18:05 Найти цитируемый пост)
Понял для чего нужен был тот вопросительный знак.. Всё-таки он был нужен.То есть вот так попровте: $reg = '/(?:\+|-)?\b\w+\b/is';

Заменить лучше вот таким: $reg = '/(?:\+|-)?\b[a-zA-Zа-яёА-ЯЁ0-9-_]+\b/is'; (это второе выражение)
И попробуйте этот злополучный "экран" поискать (без кавычек).

Цитата
что же с этой локалью ничего сделать нельзя??? Может можно на серваке установить CP1215? Как вообще в этих случаях поступают?
Тут, признаться, не силен smile 

Это сообщение отредактировал(а) kasmanaft - 19.11.2007, 19:05
PM MAIL   Вверх
Splendid
Дата 19.11.2007, 19:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 256
Регистрация: 1.8.2007
Где: Беларусь, Минск

Репутация: нет
Всего: нет



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

Код

function prepareWhere($search, $fields)
{
    if ($search!=''){
  // Разбираем строку на слова
    $reg =  '/(?:\+|-)?\b[a-zA-Zа-яёА-ЯЁ0-9-_]+\b/is';

    preg_match_all($reg, $search, $words1, PREG_PATTERN_ORDER);

    $reg = '/(?:\+|-)\b\w+\b/is';
    preg_match_all($reg, $search, $words2, PREG_PATTERN_ORDER);
    
    $words[0] = array_merge($words1[0], $words2[0]);
    
    $words_groups = array();
    $words_groups['include']=array();
    $words_groups['exclude']=array();
    $words_groups['any']=array();
    
    // Каждое слово обрабатываем, определяем его тип
    foreach( $words[0] as $word )
    {
      echo  $word = trim($word); // Удаляем лишние пробелы
        if( strlen($word) > 0 ) // Если слово не пустое, то продалжаем с ним
        {
            $word = mysql_real_escape_string($word);
            $word = addCslashes($word, '_%');
            switch( $word[0] )
            {
                case '+': // Обязательные слова
                    $words_groups['include'][] = substr($word, 1);
                    break;
                case '-': // Ненужные слова
                    $words_groups['exclude'][] = substr($word, 1);
                    break;
                default: // Наличие хотя бы одного слова
                    $word = trim($word, '"');
                    $words_groups['any'][] = $word;  
            }
        }
    }
    
    // "Группируем" группы слов, учитывая поля 
    $words_rules = array();
    $words_rules['include']=array();
    $words_rules['exclude']=array();
    $words_rules['any']=array();
    
    foreach( $fields as $field )
    {
        // Ненужные слова
        if( count($words_groups['exclude']) > 0 )
        
        $words_rules['exclude'][] = ' ('.$field.' NOT LIKE "%'. implode('%" AND '.$field.' NOT LIKE "%', $words_groups['exclude']) .'%" OR '.$field.' is null) ';
        
        // Наличие хотя бы одного слова            
        if( count($words_groups['any']) > 0 )

            $words_rules['any'][] = ' ('.$field.' LIKE "%'. implode('%" OR '.$field.' LIKE "%', $words_groups['any']) .'%") ';
    }
    
        if( count($words_groups['include']) > 0 ) 
        foreach( $words_groups['include'] as $word )
 
            $words_rules['include'][] = ' ('.implode(' LIKE "%'.$word.'%" OR ', $fields).' LIKE "%'.$word.'%") ';
            
    
    // Объединяем результаты
    if( count($words_rules['include']) > 0 )
        $where['include'] = '('.implode(' AND ', $words_rules['include']).')';
    if( count($words_rules['exclude']) > 0 )
        $where['exclude'] = '('.implode(' AND ', $words_rules['exclude']).')'; 
    if( count($words_rules['any']) > 0 )
        $where['any'] = '('.implode(' OR ', $words_rules['any']).')';
   
 $where = implode(' AND ', $where);
    return $where;
    }
}
;


Вроде все ищет, спасибо огромное!!!

Добавлено через 1 минуту
правда кавычки в кавычках все равно не воспринимаетsmile
PM MAIL   Вверх
Страницы: (3) Все [1] 2 3 
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Тексты | Следующая тема »


 




[ Время генерации скрипта: 0.1436 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.