Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Нужно читать хеш из файла  (Прочитано 10505 раз)
0 Пользователей и 1 Гость смотрят эту тему.
бУРов
Гость
« : 20-08-2010 13:03 » 

Есть файл с записями

data
{
ключ1 = значение
ключ2 = значение
...
ключN = значение
}
...

Нужно считывать записи между скобками в хеш. Есть ли в Perl какая-нибудь функция или нужно циклы делать и проверки - все ручками?
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 20-08-2010 16:11 » 

Ручками. Все универсальные инструменты требуют работы ручками. Это правило.

Но, существует понятие библиотек. Если найдешь, как данный формат называется, то в CPAN (www.cpan.org) можно попробовать найти готовый модуль для работы с ним.

На случай, если модуля нет. Обработка таких иерархических структур делается обычным конечным автоматом. Если используется только один уровень (внутри "blockname {  }" нет вложенных таких же блоков), то нужно найти идентификатор и следующее за ним открытие блока "{", после разделить пары "name = value" и найти конец блока "}". Если вложенность есть, то в алгоритм добавляется рекурсия.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
бУРов
Гость
« Ответ #2 : 20-08-2010 16:30 » 

Спасибо. Нет, вложенности нет.
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #3 : 20-08-2010 18:36 » 

Алгоритм понятен?
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
бУРов
Гость
« Ответ #4 : 20-08-2010 18:59 » 

Да, спс. Но я тут нашел интересную возможность. Попробовать использовать переменную
Код:
$/ = "}\n";
Чтобы строка была многострочной и читать весь хеш сразу. Не знаю, что получится.
Код:
while (<>) {
...
chop; # отрезать "}"
...
}
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #5 : 20-08-2010 19:02 » 

бУРов, совсем не рекомендую так поступать. Если хочется использовать подобную логику, то считай файл целиком в скаляр и далее реж регулярными выражениями.

Функцию chop вообще рекомендую забыть - это небезопасный атавизм.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
бУРов
Гость
« Ответ #6 : 20-08-2010 19:07 » 

> совсем не рекомендую так поступать
А почему. Файл сильно большой. Может быть целый гиг.

Добавлено через 21 минуту и 17 секунд:
Можно еще искать строки с "=", и читать их по счетчику (количество пар в хеше известно).
« Последнее редактирование: 20-08-2010 19:28 от бУРов » Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #7 : 21-08-2010 07:24 » 

Опасность в том, что $/ — глобальная переменная и будет влиять на все операции с файлами.

Конфиг размером с гиг? Тогда делай так:

Код:
{
    local $/ = "}\n";

    while (<>)
    {
        local $/ = "\n";
        # .....
    }
}

Первый local гарантирует, что при выходе из блока значение $/ восстановится. Второй local создает стандартную настройку внутри while и всех вызванных оттуда подпрограмм.
« Последнее редактирование: 21-08-2010 07:26 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
бУРов
Гость
« Ответ #8 : 21-08-2010 07:51 » 

Конфиг размером с гиг?
Не конфиг, файл данных.

Тогда делай так:
Да, это то, что нужно!
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #9 : 21-08-2010 07:58 » 

Наверно даже лучше так:

Код:
{
    my $save_RS = $/;
    local $/ = "}\n";

    while (<>)
    {
        local $/ = $save_RS;
        # .....
    }
}

Потому как дефолтное значение $/ может отличаться для разных платформ.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
бУРов
Гость
« Ответ #10 : 21-08-2010 08:00 » 

Почему для $/ local, а не my?
« Последнее редактирование: 21-08-2010 08:24 от бУРов » Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #11 : 21-08-2010 08:23 » 

Почитай, чем отличаются my и local.

Если кратно, то:
my - объявление локальных переменных. Лексическая область видимости: текущий блок и все вложенные.
local - объявление глобальных переменных и сохранение предыдущего состояния. Динамическая область видимости: до следующего local или до выхода из текущего блока.

Переменная $/ является глобальной.
« Последнее редактирование: 21-08-2010 08:47 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
бУРов
Гость
« Ответ #12 : 21-08-2010 08:30 » 

А еще до сих пор не вьеду, если обьявлять переменную без my (local), это что будет?

типа так:
Код:
$var = 1;
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #13 : 21-08-2010 08:35 » 

Вот тебе пример для понимания local. Кстати, $_ тоже глобальная переменная.

Код:
sub print_
{
  print "$_\n";
}

$_ = 1;
print_;

{
  local $_ = 2;
  print_;

  {
    local $_ = 3;
    print_;
  }

  print_;
}

print_;

my - обычные локальные переменные.



А еще до сих пор не вьеду, если обьявлять переменную без my (local), это что будет?

типа так:
Код:
$var = 1;

В зависимости от режима строгости.
Если локальная переменная существует, то ей присваивается новое значение.
Если локальной нет, но есть глобальная, то ей присваивается новое значение.
Если нет глобальной и режим строгого синтаксиса (strict) отключен, то создается глобальная переменная.
Если нет глобальной и режим строгого синтаксиса включен, то выдается фатальная ошибка.

Вывод: всегда используй use strict.

Добавь себе в изучение еще слово "our" - объявление глобальных переменных.

Код:
use strict;

my $var = 1;

{
  local $var = 2; # Ошибка! Глобальная переменная не объявлена ранее.
  print "$var\n";
}

print "$var\n";

Код:
use strict;

our $var = 1;

{
  local $var = 2;
  print "$var\n";
}

print "$var\n";

На понимание локальных переменных:

Код:
use strict;

my $var = 1;

{
  $var = 2;
  print "$var\n";
}

print "$var\n";

Код:
use strict;

my $var = 1;

{
  my $var = 2;
  print "$var\n";
}

print "$var\n";
« Последнее редактирование: 21-08-2010 08:46 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines