2014-01-26 2 views
0

Я хочу прочитать конфигурационный файл с нижестоящим форматом, я могу читать имена блоков, т. Е. Строки, buildid, основные, как бы я не мог читать значения каждого блока, т. Е. Переменные .buildid значения = 98 и пути файлов igd_version.h, ридми и аналогично для майораPERL: читать различные блоки в файле конфигурации

[strings] 
variables=BUILDID,MAJOR 

[BUILDID] 
VALUE=898 
VERSION.H=/home/src/gd_version.h 
readme=/home/src/readm.txt 

[MAJOR] 
VALUE=8 
IGD2.H=/home/src/igd2.h 
readme=/home/src/readm.txt 
license=/usr/src/license.html 

Вот мой код

while (<INFILE>) { 
    my $cfgLine = $_; 
    next unless ($cfgLine =~ s/\[([^]]+)\]//) ; 
    my $header = $1; 
    } 

Может некоторые тела мне предложить какие-либо идеи, я прошел через cpan (config :: tiny, config :: simple) не смог из-за изменение дизайна. Здесь «VALUE» является общей переменной для всех блоков, а имена файлов и количество файлов различны для блоков. Здесь мы можем назначить значения IGD2.h и других имен файлов и пути к переменным для проверки существования файла.

ответ

1

Если разбор этой конфигурации не является вашей центральной задачей, рассмотрите возможность использования модуля из CPAN. Config::Ini или Config::Simple вместо того, чтобы изобретать это конкретное колесо.

Если вы все еще хотите сделать разбор себя, есть три вида линий, которые вы хотите, чтобы признать:

  1. Разделов, которые могут быть описаны с помощью регулярных выражений, аналогичных ^\s*\[(.*)\]\S*$
  2. деклараций, которые может быть описано с помощью регулярного выражения, аналогичного ^\s*(.*?)\s*=\s*(.*?)\s*$
  3. Все остальное.

(Строго говоря, вы хотите использовать другой класс символов, чем . для имен разделов, ключей, значений.)

Вот что я придумал:

my $section; 
while (<STDIN>) { 
    chomp; 
    if (/^\s*\[(.*)\]\S*$/) { 
     $section = $1; 
     next; 
    } elsif (/^\s*(.*?)\s*=\s*(.*?)\s*$/) { 
     my ($key, $value) = ($1, $2); 
     say "--- $section . $key = $value"; 
    } else { 
     # invalid 
     next; 
    } 
} 
+0

hillu: это основная задача - выполнить мою другую работу. Вот почему я не смог использовать Ini и Simple modules. – user3237127

+0

hillu: от вашего кода h ow, чтобы получить значение {varilable} -> {major} -> {value} и version.h и пути файла readme – user3237127

0

Взгляните на this program строк с 328 по 371. Это я разбору файла в формате Windows INI.

SECTION_LINE и PARAMTER_LINE - константы, определенные на строках № 14 и № 15. Я сделал это, потому что я хотел убедиться, что этот хук будет работать только с стандартными модулями Perl. В противном случае я бы тоже использовал Config::INI для разбора. Это особенно верно, если вы действительно считаете, что это важная часть вашей программы.

Важно отметить, что я сравниваю строки с двумя различными регулярными выражениями. Один из них - строка заголовка раздела ([...]), а вторая - строка параметров (...=....). Мне также нужно отслеживать, когда раздел начинается и заканчивается (если я получаю другую строку заголовка раздела, предыдущий раздел заканчивается, или если я ударяю конец файла) и отслеживая, какие параметры идут с этими разделами. Я использую объекты Perl для хранения параметров со своими разделами, если вы не используете объекты, вам придется использовать сложные хеши хрелей Perl для отслеживания значений.

Также не забудьте отслеживать ошибки. Взгляните на мой код, а затем поймите, что для решения этой задачи гораздо проще использовать Config::INI.

Как я уже сказал, единственная причина, по которой я не использовал что-то вроде Config::INI, должен был убедиться, что мой код работает только с стандартными модулями Perl.Этот код работает в системах, которые пользователь не контролирует, и в этой ситуации может быть очень сложно добавить дополнительные модули CPAN Perl. Вам обычно приходится делать запрос, ждать, пока он будет заполнен, и во многих ситуациях зависит от людей, которые не знают, как это сделать.

2

Я согласен с тем, что использование модуля ini-parsing, как упомянуто, является предпочтительным. Тем не менее, возможно, следующий будет полезно:

use strict; 
use warnings; 
use Data::Dumper; 

my ($block, %hash); 

while (<DATA>) { 
    $block = $1 if /\[(.+)\]/; 
    $hash{$block}{$1} = $2 if /(\S+?)\s*=\s*(\S+)/ and defined $block; 
} 

print Dumper \%hash; 
__DATA__ 
[strings] 
variables=BUILDID,MAJOR 

[BUILDID] 
VALUE=898 
VERSION.H=/home/src/gd_version.h 
readme=/home/src/readm.txt 

[MAJOR] 
VALUE=8 
IGD2.H=/home/src/igd2.h 
readme=/home/src/readm.txt 
license=/usr/src/license.html 

Выход:

$VAR1 = { 
      'BUILDID' => { 
         'VERSION.H' => '/home/src/gd_version.h', 
         'VALUE' => '898', 
         'readme' => '/home/src/readm.txt' 
         }, 
      'MAJOR' => { 
         'VALUE' => '8', 
         'readme' => '/home/src/readm.txt', 
         'license' => '/usr/src/license.html', 
         'IGD2.H' => '/home/src/igd2.h' 
        }, 
      'strings' => { 
         'variables' => 'BUILDID,MAJOR' 
         } 
     }; 

Для доступа отдельных значений, используйте следующий шаблон:

my $value = $hash{'block'}{'key'}; 

Например:

print $hash{'BUILDID'}{'VERSION.H'}; 

Выход:

/home/src/gd_version.h 

В случае, если вы хотели бы попробовать другой INI модуль, Config::IniFiles создаст тот же НОН, как описано выше:

use strict; 
use warnings; 
use Config::IniFiles; 

tie my %hash, 'Config::IniFiles', (-file => 'config.ini'); 
print $hash{'BUILDID'}{'VERSION.H'}; 

Выход:

/home/src/gd_version.h 

Если вы не знаете, содержимое файла ini, но все же хотите получить доступ к значениям, вы можете сделать следующее - с учетом HoH сверху:

for my $block (keys %hash) { 
    print "$block:\n"; 
    for my $key (keys %{ $hash{$block} }) { 
     print "$key => $hash{$block}{$key}\n"; 
    } 

    print "\n"; 
} 

Выход:

BUILDID: 
VERSION.H => /home/src/gd_version.h 
VALUE => 898 
readme => /home/src/readm.txt 

MAJOR: 
VALUE => 8 
readme => /home/src/readm.txt 
license => /usr/src/license.html 
IGD2.H => /home/src/igd2.h 

strings: 
variables => BUILDID,MAJOR 

Вместо того, чтобы использовать привязанную хэш, вы можете использовать Config::IniFiles «s методы для доступа к данным:

use strict; 
use warnings; 
use Config::IniFiles; 

my $cfg = Config::IniFiles->new(-file => 'File.txt'); 

my @sections = $cfg->Sections; 

for my $section (@sections) { 
    print $section, "\n"; 
    my @parms = $cfg->Parameters($section); 
    for my $param (@parms) { 
     print "$param => ", $cfg->val($section, $param), "\n"; 
    } 

    print "\n"; 
} 

Выход:

strings 
variables => BUILDID,MAJOR 

BUILDID 
VALUE => 898 
VERSION.H => /home/src/gd_version.h 
readme => /home/src/readm.txt 

MAJOR 
VALUE => 8 
IGD2.H => /home/src/igd2.h 
readme => /home/src/readm.txt 
license => /usr/src/license.html 
+0

Kenosis: полезная информация, которую вы предоставили, однако, в каждом и каждом блоке только «VALUE» - это фиксированное имя параметра и другие случайны, я имею в виду, что это может быть что угодно в этом случае, как я могу назначить это фиксированному параметру, в одном блоке может быть много файлов. – user3237127

+0

@ user3237127 - добавит код, чтобы показать вам, как получить доступ к этим значениям. – Kenosis

+0

Kenosis: Большое спасибо, я могу получить свой идентификатор почты. Мне нужно получить дополнительную информацию о доступе к значениям ключей и подтверждении значений на основе ключей. – user3237127

Смежные вопросы