ФорумПрограммированиеPHP для идиотов → Regexp. CSV

Regexp. CSV

  • artoodetoo

    Сообщения: 5147 Репутация: N Группа: в ухо

    Spritz 16 октября 2010 г. 17:07, спустя 2 минуты 12 секунд

    Пример разбора CSV из Jeffrey E.F. Friedl. Mastering Regular Expressions. (rus_pdf.7z -3Mb)
    (в PHP 5.3.0 появилась функция [man]str_getcsv[/man] только речь о регулярках)


    <?php

    error_reporting(-1);

    $line = '12,"153"",2",3,4,23,6';

    $csv_regex = '{
       \G(?:^|,)
       (?:
           # Поле в кавычках…
           " # открывающая кавычка
             ( [^"]*+ (?: "" [^"]*+ )*+ )
           " # закрывающая кавычка
         | # …или…
           # …произвольный текст, кроме кавычек и запятых…
           ( [^",]*+ )
       )
    }x';

    header('Content-type: text/plain');

    /* Применить регулярное выражение, заполнить $all_matches всеми типами данных
    */
    preg_match_all($csv_regex, $line, $all_matches);
    /* В $Result будут храниться поля, которые мы извлечем из $all_matches */
    $Result = array ();
    /* Обойти все успешные совпадения… */
    for ($i = 0; $i < count($all_matches[0]); $i++)
    {
       /* Если это совпадение со второй парой сохраняющих скобок - использовать
        * значение как есть */
       if (strlen($all_matches[2][$i]) > 0)
           array_push($Result, $all_matches[2][$i]);
       else
       {
           /* Если это значение в кавычках, предварительно заменить
            * последовательности из двух кавычек одной кавычкой */
           array_push($Result, preg_replace('/""/', '"', $all_matches[1][$i]));
       }
    }
    /* Теперь массив $Result заполнен и готов к дальнейшему использованию */

    var_export($Result);
    [/php]
    выведет
    [code]
    array (
     0 => '12',
     1 => '153",2',
     2 => '3',
     3 => '4',
     4 => '23',
     5 => '6',
    )
    [/code]

    Теперь сделаем безобидное, вроде бы, изменение: добавим пробелы.
    [php]
    $line = ' 12 , "153"" , 2" , 3 , 4, 23, 6 ';
    [/php]
    Логика нам подсказывает, что строка соответствует тем же самым данным. А наша регулярка облажалась:
    [code]
    array (
     0 => ' 12 ',
     1 => '  ',
    )
    [/code]
    Методом тыка я нашел такой способ оживления. Первую фразу резулярки сделаем такой:
    [code]
       \G(?:^|\s*?,\s*?)
    [/code]
    вместо  \s*? можно написать \s*+
    результат:
    [code]
    array (
     0 => ' 12 ',
     1 => '153" , 2',
     2 => '3 ',
     3 => '4',
     4 => '23',
     5 => '6 ',
    )
    [/code]
    Неплохо, только у под-строк, не заключённых в кавычки, появляются лишние концевые пробелы. В принципе это лечится пост-обработкой trim(), но неприятный осадочек есть.

    Профи, подскажите новичку [b]лучшую[/b] регулярку для этих же целей.




    ιιlllιlllι унц-унц
  • NRG

    Сообщения: 4761 Репутация: N Группа: в ухо

    Spritz 16 октября 2010 г. 12:34, спустя 19 часов 26 минут 48 секунд

    я в регулярках не силен.
    профи обосрались)
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 16 октября 2010 г. 12:42, спустя 7 минут 26 секунд

    такие вещи не регулярками разбирают … еще раз повторяю .. а автоматами, регулярками всегда проблемы будут
    Сапожник без сапог
  • kostyl

    Сообщения: 5210 Репутация: N Группа: Джедаи

    Spritz 16 октября 2010 г. 12:50, спустя 8 минут 11 секунд

    artoodetoo, конечные автоматы рулят!!!

    А вообще должны уже быть готовые решения…
    Спустя 29 сек.
    дуд меня опередил
  • artoodetoo

    Сообщения: 5147 Репутация: N Группа: в ухо

    Spritz 16 октября 2010 г. 13:36, спустя 46 минут 15 секунд

    Регулярное выражение и есть "недетерминированный конечный автомат". Так что не надо ля-ля ))) Просто скажите: "не шарим".
    ιιlllιlllι унц-унц
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 16 октября 2010 г. 13:39, спустя 2 минуты 23 секунды

    artoodetoo, ну давай профи жги, а я куплю попкорна и поржу за твои ошибки :D
    Спустя 9 сек.
    знаем, плавали
    Сапожник без сапог
  • VaseninM

    Сообщения: 2416 Репутация: N Группа: Адекваты

    Spritz 16 октября 2010 г. 14:04, спустя 25 минут 38 секунд

    Гавно какое то по моему.
    <?php

    class Csv {

    private $_file = NULL;
    private $_array = array();
    private $_det = '';
    private $_length = 0;

    public function __construct ($filename, $det = ',', $length = 0) {
    $this->_file = $filename;
    $this->_det = $det;
    $this->_length = $length;
    $this->_open();
    }

    public function read ($id = false) {
    if ($id === false) {
    return $this->_array;
    } else {
    return $this->_array[intval($id)];
    }
    }

    private function _open () {
    if (!file_exists($this->_file)) throw new Exception ('File not exists: ' . $this->_file);
    $file = fopen($this->_file, 'r');
    $column = fgetcsv($file, $this->_length, $this->_det);
    if ($column === false) throw new Exception ('Wrong CSV file.');
    $column = array_map('trim', $column);
    $numColumns = count($column);
    while (($data = fgetcsv($file, $this->_length, $this->_det)) !== FALSE) {
    if ($numColumns !== count($data)) throw new Exception ('Wrong CSV file.');
    $this->_array[] = array_combine($column, $data);
    }
    fclose($file);
    }
    }


        $csv = new Csv('./csv/tdnam_all_listings.csv', ',');
    $domains = $csv->read();
  • Абырвалг

    Сообщения: 6480 Репутация: N Группа: Джедаи

    Spritz 16 октября 2010 г. 14:07, спустя 2 минуты 45 секунд

    SpartakuS, ему может нужно не с файла. И не хочется через tmpfile писать
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 16 октября 2010 г. 14:19, спустя 12 минут 16 секунд

    р2д2, ты посмотри исходники fgetcsv пхп функции, да повтории ее на пыхе да и все, к ней нареканий у меня не было никогда, отрабатывает на ура
    Сапожник без сапог
  • artoodetoo

    Сообщения: 5147 Репутация: N Группа: в ухо

    Spritz 16 октября 2010 г. 14:54, спустя 35 минут 5 секунд

    мне реально не надо из файла. понадобилось для ввода поисковых тегов.
    дуд, ну посмотрю я fgetcsv, как я это смогу использовать? может всё-таки с регуляркой немного потанцуем?
    ιιlllιlllι унц-унц
  • arvitaly

    Сообщения: 292 Репутация: N Группа: Адекваты

    Spritz 16 октября 2010 г. 15:48, спустя 54 минуты 13 секунд

    Регулярка намного намного дольше будет работать чем автомат (а тут и нужен то несложный)
  • VaseninM

    Сообщения: 2416 Репутация: N Группа: Адекваты

    Spritz 16 октября 2010 г. 15:51, спустя 2 минуты 16 секунд

    artoodetoo, может тогда эти самые конченыеконечные автоматы. Я сам регулярки люблю, но ты щас как главрыб уперся.
    Нельзя юзать статические методыконечные автоматы.
  • arvitaly

    Сообщения: 292 Репутация: N Группа: Адекваты

    Spritz 16 октября 2010 г. 15:53, спустя 2 минуты 4 секунды

    бля а как зачеркнутый делать я в тот раз хотел не нашел
  • artoodetoo

    Сообщения: 5147 Репутация: N Группа: в ухо

    Spritz 16 октября 2010 г. 16:01, спустя 7 минут 48 секунд

    нахуй зачем
    Спустя 244 сек.
    SpartakuS, я не уперся. Может я чего-то не понимаю? RegExp - К.А. Написаны на C. Ты не будешь утверждать, что разбор К.А. на PHP будет работать быстрее?
    Спустя 98 сек.
    Конечно регулярки тоже можно писать коряво. Вот в первом посте какраз упоминается книжка, посвященная анализу regexp.
    ιιlllιlllι унц-унц
  • Абырвалг

    Сообщения: 6480 Репутация: N Группа: Джедаи

    Spritz 16 октября 2010 г. 17:05, спустя 1 час 4 минуты 40 секунд


    Нельзя юзать статические методыконечные автоматы.


    ага, скоро меня еще и фотожабить будут)

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