Шаблонный поиск по файлу php

Discussion in 'PHP' started by banned, 30 Mar 2011.

  1. banned

    banned Banned

    Joined:
    20 Nov 2006
    Messages:
    3,325
    Likes Received:
    1,194
    Reputations:
    252
    Hey guys.

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

    PHP:
    <?php
        
    /*
        •    apple banana – производит поиск на содержание по меньшей мере одно из этих слов. 
    Т.е. мы тупо ищем в файле либо либо, либо другое и выводим "Нашли", а что нашли надо говорить?
    •    +apple +juice – обязательно оба слова
    если нашли apple, но не нашли juice, то говорим что нихрена не нашли
    •    +apple +juice – обязательно оба слова
    •    +apple macintosh – обязательно apple, но не обязательно macintosh
    т.е. если в файле нету apple, но есть macintosh, то говорим ок, нашли
    •    +apple -macintosh – обязетельно слово apple, не должно быть слова macintosh
    если нашли apple И нашли macintosh, то говорим что ничего не нашли
    •    apple* – Поиск должен находить apple, apples, applesauce, и applet. 
    любое наличие apple* выводим ОК
    •    "some words" – Поиск по точной фразе вхождения.
    ок
    */
        
    $template '+apple +banana';
        
        if (
    strpos($template' '))
        {
            
    $a explode(' '$template);
            
    $file file_get_contents('test.txt');
            
    $find = array();
            
    /*
            apple banana
            foreach ($a as $value)
            {
                if (preg_match("#[ \r\n\t]" . $value . '[ \r\n\t]#', $file, $s))
                {
                    $find = true;
                }
            }*/
            
    foreach ($a as $key => $value)
            {
                if (
    $value[0] == '+')
                {
                    
    $value substr($value1);
                    
    var_dump($value);
                    if (
    preg_match("#[ \r\n\t]" $value '[ \r\n\t]#'$file$s))
                    {
                        
    $find[$key] = true;
                    }
                    else
                    {
                        
    $find[$key] = false;
                    }
                }
            }
        }
        
        
    var_dump($find);
    В коде закомментирован пример для первого правила, когда найдено вхождение или apple или banana.
    Но дальше я не могу придумать для других правил, как все-таки проверять эти шаблоны..
     
  2. Fuckel

    Fuckel Banned

    Joined:
    16 Jan 2008
    Messages:
    274
    Likes Received:
    59
    Reputations:
    6
    Для шаблонов вида:
    +apple +banana
    +apple -banana
    +apple banana

    написал так:

    PHP:
    <?php

    $template 
    "+banana -apple";
    $fileContent 'banana apple';

    $parts explode(' '$template);
    $validKeys '+-';

    $state = array();
    $wordCount count($parts);
    for (
    $i 0$i $wordCount$i++) {

      
    $key $parts[$i]{0};

      if (
    strpos($validKeys$key) !== false) {
        
    $word substr($parts[$i], 1);
      } else {
        
    $word $parts[$i];
      }

      
    $state[$i] = (boolean) preg_match("/\b{$word}\b/i"$fileContent);
      if (
    $key == '-') {
        
    $state[$i] = !$state[$i];
      }

    }

    var_dump($state);
    в массиве $state хранятся состояния выполнения каждой части шаблона. Для наглядности можно представить в виде ассоциативного массива $state[$parts[$i]] = ...
     
    #2 Fuckel, 30 Mar 2011
    Last edited: 30 Mar 2011
    1 person likes this.
  3. Fuckel

    Fuckel Banned

    Joined:
    16 Jan 2008
    Messages:
    274
    Likes Received:
    59
    Reputations:
    6
    А вообще идеи:
    Если использовать регулярки, то экранировать спецсимволы.

    Проверить на противоречия в правилах поиска и если есть, то выдать false. Например, +banana -banana Либо выделить уникальные слова.

    Сгруппировать правила при поиске, например, для
    +banana foo +bar -train
    preg_match('/\b(banana|foo|bar|train)\b/i', 'foo train bar', $m);
    и дальше парсить результат $m
     
  4. banned

    banned Banned

    Joined:
    20 Nov 2006
    Messages:
    3,325
    Likes Received:
    1,194
    Reputations:
    252
    Во втором посте не совсем то что надо.. результат в принципе получили, отлично. Но как теперь этот результат вернуть к одному true или false исходя из правила.
    Т.е. файл

    apple
    banana
    juice

    Правило:
    1) apple banana вернет true
    2) +apple +macintosh вернет false
    3) +apple -banana вернет false
     
  5. Fuckel

    Fuckel Banned

    Joined:
    16 Jan 2008
    Messages:
    274
    Likes Received:
    59
    Reputations:
    6
    PHP:
    $result true;
    for (
    $i 0$i count($state); $i++) {
      
    $result &= $state[$i];
    }
    var_dump($result);
    наверное, можно без цикла, но пока ничего другого.

    Или так:
    PHP:
    var_dump(array_sum($state) == count($state));
    :)
     
    #5 Fuckel, 30 Mar 2011
    Last edited: 30 Mar 2011
  6. banned

    banned Banned

    Joined:
    20 Nov 2006
    Messages:
    3,325
    Likes Received:
    1,194
    Reputations:
    252
    Охуенно, спасибо!
     
  7. banned

    banned Banned

    Joined:
    20 Nov 2006
    Messages:
    3,325
    Likes Received:
    1,194
    Reputations:
    252
    Блеать, логика опять нарушилась...

    PHP:
    $template '+ПАУСТОВСКИЙ banananana';
    $content 'Константин Георгиевич ПАУСТОВСКИЙ (1892 1968) Революция, гражданская война, разруха, голод. Константин Паустовский был свидетелем исторических перемен —времени, когда ';
    $parts explode(' '$template);
                
    $validKeys '+-';

                
    $state = array();
                
    $wordCount count($parts);
                for (
    $i 0$i $wordCount$i++)
                {
                    
    $key $parts[$i]{0};

                    if (
    strpos($validKeys$key) !== false)
                    {
                        
    $word substr($parts[$i], 1);
                    }
                    else
                    {
                        
    $word $parts[$i];
                    }


                    
    $content iconv(mb_detect_encoding($content"auto"), 'utf-8'$content);

                    
    /*if (preg_match("#[ \r\n\t]" . $word . "[ .,\-\r\n\t]#ui", $content))
                    {
                        var_dump('sss');
                    }*/
                    
                    
    $state[$i] = (boolean) preg_match("#[ \r\n\t]" $word "[ .,\-\r\n\t]#ui"$content);
                    if (
    $key == '-')
                    {
                        
    $state[$i] = !$state[$i];
                    }
                }
                
                return 
    array_sum($state) == count($state);
    Возвращает false, а надо true. ПАУСТОВСКИЙ найдено, а bananana нет..

    И в preg_match \b не работает с русскими буквами, поэтому приходится [ .,\-\r\n\t] вот так
     
  8. Deathdreams

    Deathdreams Elder - Старейшина

    Joined:
    8 Nov 2008
    Messages:
    342
    Likes Received:
    116
    Reputations:
    5
    Isis Пробуй максимально упрощать данный функции текст (убирать различные пустые строки и ненужные символы), а потом регулярками да и только
    Помог бы, но с денвером проблема...
     
    1 person likes this.
  9. Fuckel

    Fuckel Banned

    Joined:
    16 Jan 2008
    Messages:
    274
    Likes Received:
    59
    Reputations:
    6
    В cp1251 \b исполняет правильно
    PHP:
    <?php

    $template 
    "+ПАУСТОВСКИЙ banananana";
    $fileContent 'Константин Георгиевич ПАУСТОВСКИЙ (1892 1968) Революция, гражданская война, разруха, голод. Константин Паустовский был свидетелем исторических перемен —времени, когда ';

    $parts explode(' '$template);
    $validKeys '+-';

    $state $keys = array();
    $wordCount count($parts);
    for (
    $i 0$i $wordCount$i++) {

      
    $key $parts[$i]{0};
      
    $keys[$i] = $key;

      if (
    strpos($validKeys$key) !== false) {
        
    $word substr($parts[$i], 1);
      } else {
        
    $word $parts[$i];
      }

      
    $state[$i] = (boolean) preg_match("/\b{$word}\b/i"$fileContent);
      if (
    $key == '-') {
        
    $state[$i] = !$state[$i];
      }

    }

    //var_dump($state);

    $result true;
    for (
    $i 0$i count($state); $i++) {
      if (
    strpos($validKeys$key) !== false) {
        
    $result $result && $state[$i];
      }
    }
    var_dump($result);

     
    1 person likes this.
  10. banned

    banned Banned

    Joined:
    20 Nov 2006
    Messages:
    3,325
    Likes Received:
    1,194
    Reputations:
    252
    Спасибо огромное. Я привык писать в файлах utf8 поэтому cp1251 мне не подойдет.
     
  11. banned

    banned Banned

    Joined:
    20 Nov 2006
    Messages:
    3,325
    Likes Received:
    1,194
    Reputations:
    252
    Fuckel, блин блинский))
    Если задать шаблон из фраз которых нету вообще в файле, то он возвращает true ... Пробовал менять изначальный result на false - работает, но когда опять сделать темплейт как в прошлом примере, то не пашет.. Логика такая логика, как быть? =)
     
  12. Fuckel

    Fuckel Banned

    Joined:
    16 Jan 2008
    Messages:
    274
    Likes Received:
    59
    Reputations:
    6
    нашел достаточно ошибок в своем коде:
    PHP:
    <?php 

    $template 
    "+ПАУСТОВСКИЙ banananana";
    $fileContent 'Константин Георгиевич ПАУСТОВСКИЙ (1892 1968) Революция, гражданская война, разруха, голод. Константин Паустовский был свидетелем исторических перемен —времени, когда ';

    $parts explode(' '$template); 
    $validKeys '+-'

    $result null;
    $optResult false;
    $wordCount count($parts);
    for (
    $i 0$i $wordCount$i++) { 

      
    $key $parts[$i]{0}; 

      if (@
    strpos($validKeys$key) !== false) {
        
    $word substr($parts[$i], 1); 
      } else { 
        
    $word $parts[$i]; 
      } 

      
    $state = (boolean) preg_match("/[ \r\n\t]{$word}[ .,\-\r\n\t]/i"$fileContent);

      
      if (
    $key == '-') { 
        
    $state = !$state
      }
      
      if (@
    strpos($validKeys$key) !== false) {
        
    $result = ($result === null) ? $state $result && $state;
      } else {
        
    $optResult $optResult || $state;
      }
      



    $result $result === null $optResult $result;
    echo (
    'Результат: ' . ($result 'найдено' 'не найдено'));

     
    #12 Fuckel, 31 Mar 2011
    Last edited: 31 Mar 2011
  13. banned

    banned Banned

    Joined:
    20 Nov 2006
    Messages:
    3,325
    Likes Received:
    1,194
    Reputations:
    252
    Сейчас проверю, а зачем ты собачки ставишь перед strpos? Она же в условии стоит
     
    1 person likes this.
  14. astrologer

    astrologer Elder - Старейшина

    Joined:
    30 Aug 2007
    Messages:
    837
    Likes Received:
    267
    Reputations:
    59
    Задание самопротиворечивое =/

     
  15. banned

    banned Banned

    Joined:
    20 Nov 2006
    Messages:
    3,325
    Likes Received:
    1,194
    Reputations:
    252
    Тут я просто не так объяснил ))
    На самом деле тут самому не понятно.. если не нашли первое, то второе зачем указывать, хрен поймешь..
     
  16. Fuckel

    Fuckel Banned

    Joined:
    16 Jan 2008
    Messages:
    274
    Likes Received:
    59
    Reputations:
    6
    Заглушки для пустого запроса. Можно еще break в цикл воткнуть, чтобы почем зря не крутил)
     
Loading...