Logo Море(!) аналитической информации!
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware
Архив форумов ЦИТФорума
Море(!) вопросов - Море(!) ответов
 
 FAQFAQ   ПоискПоиск   ПользователиПользователи   ГруппыГруппы   РегистрацияРегистрация 
 ПрофильПрофиль   Войти и проверить личные сообщенияВойти и проверить личные сообщения   ВходВход 
Как правильно задавать вопросы

(Perl) Как выгрузить в файл текст который лежит в хеше?

 
Перейти:  
Этот форум закрыт, вы не можете писать новые сообщения и редактировать старые.   Эта тема закрыта, вы не можете писать ответы и редактировать сообщения.    Список форумов Архив форумов ЦИТФорума -> Программирование
Предыдущая тема :: Следующая тема  
Автор Сообщение
rubin



Зарегистрирован: 15.06.2006
Сообщения: 5
Откуда: Санкт-Петербург

СообщениеДобавлено: Чт Июн 15 2006 16:25    Заголовок сообщения: (Perl) Как выгрузить в файл текст который лежит в хеше? Ответить с цитатой

Добрый День.
Есть у меня одна проблема, я написал парсер на Perl (беру файл, запихиваю его в массив, далее построчно регулярными выражениями распихиваю строки по хешам как мне надо, соблюдая структуру начального файла). Теперь когда у меня файл разложен в хеше его надо выгрузить в другой файл в том же виде и порядке как и в исходном файле, а вот как это сделать - понять не могу. Может кто подскажет?

Код:
#!/usr/bin/perl -wopen
(FILEHANDLE, "<services3.cfg"); # открываем файл для чтения
@text = <FILEHANDLE>; # передаем в массив содержимое
FILEHANDLEclose (FILEHANDLE);
%hash = (); # создаю пустой хеш
$var = 0;
$temp = 0;
$val = "val";
$rem = "rem";
$keystone = '';
$open = 0;
for ($loop_ind=0; $loop_ind<=$#text; $loop_ind++) # открываю цикл по строкам FILEHANDLE
{ #проверка пустой стоки текста
if ($text[$loop_ind] =~ m/(^$)|(\x09)|([\ ]+\n)/)
{ if ($open == 0)
{$var++;
$hash{$var} = $text[$loop_ind];
}
else
{ if ($num == 0)
{$keystone = "Clear";
if ((ref $hash{$var}{$temp}{$num}) eq 'HASH')
{$hash{$var}{$temp}{$num}{$keystone} -> {$rem} = $text[$loop_ind];}
else
{$hash{$var}{$temp}{$num} = {$keystone => {$rem => $text[$loop_ind]}};}
}
else
{$keystone = "Clear";
$num++;
$hash{$var}{$temp}{$num}{$keystone} -> {$rem} = $text[$loop_ind]; }
}
}
else
{# проверка строки на наличие символов "закрытия секции"
if ($text[$loop_ind] =~ m/([\ ]+)*(\})/)
{if ($text[$loop_ind] =~ m/(\#)/)
{}
else
{ if ($text[$loop_ind] =~ m/(\;)/)
{# проверка строки на наличие символов "закрытия секции" с коментариями
if ($text[$loop_ind] =~ m/([\ ]+)*(\})*([\ \x09]+)*(\;)*([\ \x09]+)*([\W\w\d\'\"\S\s\n]+)/)
{$keystone = "Clear";
$num++;
$hash{$var}{$temp}{$num}{$keystone} -> {$val} = $1.$2.$3.$4.$5.$6;
$open = 0;
}
}
else
{$keystone = "Clear";
$num++;
$hash{$var}{$temp}{$num}{$keystone} -> {$val} = $text[$loop_ind];
$open = 0;
}
}
}
else
{# проверка строки на наличие "шарпа" - вся строка записывается как ремарка
if ($text[$loop_ind] =~ m/(\#)/)
{if ($open == 0)
{$var++;
$hash{$var} = $text[$loop_ind];
}
else
{if ($num == 0)
{$keystone = "Sharp";
if ((ref $hash{$var}{$temp}{$num}) eq 'HASH')
{$hash{$var}{$temp}{$num}{$keystone} -> {$rem} = $text[$loop_ind];}
else
{$hash{$var}{$temp}{$num} = {$keystone => {$rem => $text[$loop_ind]}};}
}
else
{$keystone = "Sharp";
$num++;
$hash{$var}{$temp}{$num}{$keystone} -> {$rem} = $text[$loop_ind];
}
}
}
else
{# проверка строки на предмет начала секции
if ($text[$loop_ind] =~ m/(define)*(\ )*([A-Za-z]+) *(\{)/)
{if ($text[$loop_ind] =~ m/(\;)/)
{# проверка строки на предмет начала секции с коментариями
if ($text[$loop_ind] =~ m/(define)*(\ )*([A-Za-z]+) *(\{)*([\ \x09]+)*(\;)*([\ \x09]+)*([\W\w\d\'\"\S\s\n]+)/)
{$var++;
$num = 0;
$open = 1;
$temp = $1.$2.$3.$4.$5.$6.$7.$8;
$hash{$var}{$temp} = {$num =>''};
}
}
else
{$var++;
$num = 0;
$open = 1;
$temp = $1.$2.$3.$4;
$hash{$var}{$temp} = {$num =>''};
}
}
else
{# проверка строки пренадлежащей к секции на наличие коментариев
if ($text[$loop_ind] =~ m/(\;)/)
{# парсинг строки с коментариями
if ($text[$loop_ind] =~ m/([\ \x09]+)*([A-Za-z\_\-]+)*([\ \x09]+)*([A-Za-z\d\_\-\!\%\:\"\,\.\n]+)*([\ \x09]+)*(\;)*([\ \x09]+)*([\W\w\d\'\"\S\s\n]+)/)
{if ((ref $hash{$var}{$temp}{$num}) eq 'HASH')
{$keystone = $2;
$num++;
$hash{$var}{$temp}{$num}{$keystone} -> {$val} = $4;
$hash{$var}{$temp}{$num}{$keystone} -> {$rem} = $8;
}
else
{$keystone = $2;
if ($num == 0)
{$hash{$var}{$temp}{$num} = {$keystone => {$val => $4}};
$hash{$var}{$temp}{$num}{$keystone} -> {$rem} = $8;
}
else
{$num++;
$hash{$var}{$temp}{$num} = {$keystone => {$val => $4}};
$hash{$var}{$temp}{$num}{$keystone} -> {$rem} = $8;
}
}
}
}
else
{# парсинг строки без коментариев
if ($text[$loop_ind] =~ m/([\ \x09]+)*([A-Za-z\_\-]+)*([\ \x09]+)*([A-Za-z\d\_\-\!\%\:\"\,\.\n]+)/)
{if ((ref $hash{$var}{$temp}{$num}) eq 'HASH')
{$keystone = $2;
$num ++;
$hash{$var}{$temp}{$num}{$keystone} -> {$val} = $4;
$hash{$var}{$temp}{$num}{$keystone} -> {$rem} = "\n";
}
else
{$keystone = $2;
if ($num == 0)
{$hash{$var}{$temp}{$num} = {$keystone => {$val => $4}};
$hash{$var}{$temp}{$num}{$keystone} -> {$rem} = "\n";
}
else
{$num ++;
$hash{$var}{$temp}{$num} = {$keystone => {$val => $4}};
$hash{$var}{$temp}{$num}{$keystone} -> {$rem} = "\n";
}
}
}
}
}
}
}
}
}
При этом содержимое исходного файла services3.cfg такое:

Код:
# test message
define service{ ; sdfsadf
name generic-service ; The 'name' of this service template, referenced in other service de
active_checks_enabled 1 ; Active service checks are enable
register 0 ; DONT REGISTER THIS DEFINITION - ITS NOT A REAL SERVICE, JUST A TEMPLATE!
} ; temp message
# test message
define service{ use generic-service
host_name router-fcu
}
# Service definition
#define service{
# use generic-service ; Name of service template to use
#
# notification_period 24x7
# }
Секция начинается с "define service{", а заканчивается " }".
Собственно как мне записать распарсенный текст в таком же виде построчно выкинув его в новый файл format.cfg???
Все сто стоит после шарпа "#" - это ремарка или просто коментарий.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Посетить сайт автора
Aragaer



Зарегистрирован: 28.03.2005
Сообщения: 164

СообщениеДобавлено: Чт Июн 15 2006 20:37    Заголовок сообщения: Ответить с цитатой

Рекурсивно....
Обход сколь угодно страшной структуры делается примерно так:
Код:
sub Unparse {
   $_ = shift;
   $prefix = shift;
   if (ref eq "SCALAR") {
      Unparse($$_, $prefix)
   } elsif (ref eq "ARRAY") {
      my @a = @$_;
      Unparse($a[$_], "$prefix["."$_]") for 0..$#a
   } elsif (ref eq "HASH") {
      my %a = %$_;
      Unparse($a{$_}, "$prefix{"."$_}") for keys %a
   } else { # Кажется наткнулись на не-ссылку (или что-то blessнутое)
      Сделать что-то интересное. Например так:
      print "$prefix = $_";
   }
}

_________________
Open your eyes.
And Awaken.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
rubin



Зарегистрирован: 15.06.2006
Сообщения: 5
Откуда: Санкт-Петербург

СообщениеДобавлено: Пт Июн 16 2006 08:51    Заголовок сообщения: Ответить с цитатой

Большое спасибо.
Про рекурсивный метод я подумывал уже (прочитав о нем в книге).
Но так как я язык этот изучаю всего 1,5 недели, то мне трудно еще во все въехать!
В частности не могли бы Вы Aragaer, слегка разжевать написанный код, просто не совсем понимаю что, от куда и куда. Дальше буду переделывать под себя.
Спасибо.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Посетить сайт автора
Aragaer



Зарегистрирован: 28.03.2005
Сообщения: 164

СообщениеДобавлено: Пт Июн 16 2006 08:58    Заголовок сообщения: Ответить с цитатой

На вход мы получаем некий скаляр, который может быть ссылкой на что-либо, а может быть собственно литерадом (значение, которое надо вывести). Если это ссылка - разыменовываем ее и продолжаем мучаться. Ссылка на массив - разбираем каждый элемент массива. На хеш - каждый элемент хеша. Переменная $prefix в моем примере отслеживает глубину вложения.

В том виде, как я написал, скрипт не будет работать с объектами - они попадут на else, а должны попасть куда-то еще. Имеет смысл сделать так:
Код:
 } elsif (!ref) {
    работаем с литералом
 } else {
    а вот теперь уже точно какой-то левый объект
 }


Хотя да, код у меня получился немного навороченным (в смысле использует прорву особенностей языка....) Попробую попозже написать его более внятно.
_________________
Open your eyes.
And Awaken.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
rubin



Зарегистрирован: 15.06.2006
Сообщения: 5
Откуда: Санкт-Петербург

СообщениеДобавлено: Пт Июн 16 2006 09:10    Заголовок сообщения: Ответить с цитатой

Да уж, без пол литра не разберешься!
А можно мне в аську писать?
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Посетить сайт автора
rubin



Зарегистрирован: 15.06.2006
Сообщения: 5
Откуда: Санкт-Петербург

СообщениеДобавлено: Пт Июн 16 2006 10:14    Заголовок сообщения: Ответить с цитатой

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

%hash = ...
   1 = '\n'
   2 = '#define service{\n'
   3 = '#        name                            generic-service ; The \\'name\\' of this service template, \n'
   4 = '#        active_checks_enabled           1       ; Active service checks are enabled\n'
   5 = '# жЕДЕТБМШОЩК гЕОФТ хРТБЧМЕОЙС\n'
   6 = '   \n'
   7 = '\n'
   8 = HASH(0x1d2ae98)...
      'define service{' = HASH(0x1d2aee0)...
         0 = HASH(0x1ae8020)...
            'use' = HASH(0x1ae7e7c)...
               'rem' = 'Test rem\n'
               'val' = 'generic-service'
         1 = HASH(0x1ae7bb8)...
            'host_name' = HASH(0x1cd6298)...
               'rem' = 'woeirjwerfwf\n'
               'val' = 'router-fcu'
         10 = HASH(0x1d2add8)...
            'contact_groups' = HASH(0x1ae8200)...
               'rem' = '\n'
               'val' = 'admins\n'
         11 = HASH(0x1ae7cd8)...
            'notification_interval' = HASH(0x1ae7f3c)...
               'rem' = '\n'
               'val' = 120\n
         12 = HASH(0x1d2ae08)...
            'notification_period' = HASH(0x1ae8668)...
         13 = HASH(0x1d2aec8)...
         14 = HASH(0x1d2af40)...
         15 = HASH(0x1d2afa0)...
         2 = HASH(0x1d5a970)...
         3 = HASH(0x1ae7d08)...Cut...
         4 = HASH(0x1d2adb4)...Cut...
         5 = HASH(0x1d36948)...Cut...
         6 = HASH(0x1ae8248)...Cut...
         7 = HASH(0x1ae8404)...Cut...
         8 = HASH(0x1ae8734)...Cut...
         9 = HASH(0x1ae8998)...Cut...
   9 = HASH(0x1d2afdc)...Cut...


Так вот мне надо в новый файл сначала выкинуть строку "1 = '\n'" проверив ее, является ли она хешем, если нет то вывести ее в опр. формате, когда дело дойдет до строки "8 = HASH(0x1d2ae98)...", то при проверке на хеш, заходим в него, проверяем является ли "'define service{' = HASH(0x1d2aee0)..." хешем, если да то снова заходим в него, и т.д. пока не наткнемся на НЕ хеш. причем выводить строки мне надо по номерам(в данном случае с 1-7, потом всю внутрянку 8-ого (с 0 - 15), потом внутр 9 и т.д.
Что делать то я знаю, а вот как это писать понять не могу!!!
Хелп ми, плиз.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Посетить сайт автора
Aragaer



Зарегистрирован: 28.03.2005
Сообщения: 164

СообщениеДобавлено: Пт Июн 16 2006 12:17    Заголовок сообщения: Ответить с цитатой

Дык.. ну вон прямо тот код, который я написал, только там
Код:
   } elsif (ref eq "HASH") {
      my %a = %$_;
      Unparse($a{$_}, "$prefix{"."$_}") for sort {$a <=> $b} keys %a
   }

sort {$a <=> $b} дает еще и численную сортировку (по умолчанию сортировка по алфавиту - см отписание функции sort)

Чтобы отличить ссылку на хеш от литерала (ну .. просто строки) как раз и используется команда ref. в моем примере она без аргумента, потому что саму строку я предварительно закинул в $_ (переменные по умолчанию - страшное зло Twisted Evil)
_________________
Open your eyes.
And Awaken.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
Показать сообщения:   
Этот форум закрыт, вы не можете писать новые сообщения и редактировать старые.   Эта тема закрыта, вы не можете писать ответы и редактировать сообщения.    Список форумов Архив форумов ЦИТФорума -> Программирование Часовой пояс: GMT + 3
Страница 1 из 1

 
Перейти:  
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах


Powered by phpBB © 2001, 2002 phpBB Group
Русская поддержка phpBB

 

IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

Информация для рекламодателей PR-акции, размещение рекламы — adv@citforum.ru,
тел. +7 495 6608306, ICQ 232284597
Пресс-релизы — pr@citforum.ru
Послать комментарий
Информация для авторов
This Web server launched on February 24, 1997
Copyright © 1997-2000 CIT, © 2001-2006 CIT Forum
Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...