Perl - загрузка записей из файла в хеш - PullRequest
4 голосов
/ 28 февраля 2012

Можно ли загрузить записи из файла прямо в хеш, пожалуйста?Записи разделяются символами / begin и / end и имеют фиксированный порядок содержимого.

Мне нужен хеш, заполняемый следующим образом:

hash_city{London}{slurped_record}='/begin CITY London\n   big\n   England\n   Sterling\n/end CITY'
hash_city{Paris}{slurped_record}='/begin CITY\n   Paris\n   big\n   France\n   Euro\n/end CITY'
hash_city{Melbourne}{slurped_record}='/begin CITY\n\n   Melbourne\n   big\n   Australia\n   Dollar\n   hot\n/end CITY'

Затем я могу отключиться иобрабатывать записи в хэше и т. д. (причина записи «slurped_record» позже, я хочу добавить новые ключи, например, «Лондон = Англия» и т. д.

hash_city{London}{Country}='England'

Мне удалосьдостичь чего-то, что работает, путаясь вместо того, чтобы читать файл построчно. Сопоставление с / begin, построение записи ($ rec. = $ _), затем сопоставление с / end и обработка. Это немного грязно иИнтересно, был ли более элегантный подход Perl ..

Моя попытка кода до сих пор выглядит следующим образом:

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

my $string = do {local $/; <DATA>};
my %hash_city = map{$2=>$1} $string =~ /(\/begin\s+CITY\s+(\w+).+\/end\s+CITY)/smg;
print Dumper(%hash_city);

__DATA__
stuff
stuff
/begin CITY London
   big
   England
   Sterling
/end CITY

stuff
stuff

/begin CITY
   Paris
   big
   France
   Euro
/end CITY
stuff

/begin CITY

   Melbourne
   big
   Australia
   Dollar
   hot
/end CITY

stuff

Ответы [ 3 ]

3 голосов
/ 28 февраля 2012

Сделал небольшую программу, чтобы показать обратное, продвигая ваш процесс.Не знаю, элегантно ли это или нет, но я полагаю, что оно выполнит свою работу.)

my %city_record;

## we're going to process the input file in chunks.
## here we define the chunk start marker, and make Perl to separate file input with it
local $/ = "/begin CITY";

# ignoring anything before the first section starts
scalar <DATA>;

while (<DATA>) {
  # throwing out anything after the section end marker
  # (might be done with substr-index combo as well, 
  # but regex way was shorter and, for me, more readable as well )
  my ($section_body) = m{^(.+)/end CITY}ms;

  # now we're free to parse the section_body as we want. 
  # showing here pulling city name - and the remaining data, by using the split special case
  my ($city, @city_data) = split ' ', $section_body;

  # filling out all the fields at once
  # (may seem a bit unusual, but it's a simple hash slice actually, great Perl idiom)
  @{ $city_record{$city} }{qw/ size country currency misc /} = @city_data;
}

# just to test, use something of yours instead. )
print Dumper \%city_record;
1 голос
/ 28 февраля 2012

Возможно, вы можете использовать оператор триггер : /FROM/ .. /TO/. Вы можете использовать другой разделитель, чтобы сделать регулярное выражение более читабельным. Я использую m#^/begin ...# ниже. Извлечь название города просто, при условии, что между заголовком и названием города есть только пробел. Я использую \S (без пробелов), так как вы не хотите пропустить названия городов с не буквенно-цифровыми символами в названии, например "Foo-Bar" или "St.Tropez".

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

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

my %hash;
my $string;
while (<DATA>) {
    if (m#^/begin CITY# .. m#^/end CITY#) {
        $string .= $_;
        if (m#^/end CITY#) {
            my ($city) = $string =~ m#^/begin CITY\s*(\S+)#;
            $hash{$city}{slurp} = $string;
            $string = "";
        }
    }
}
$Data::Dumper::Useqq=1;
print Dumper(\%hash);
0 голосов
/ 28 февраля 2012

Это даст вам хэш со всеми городами и их свойствами :

my %cities = map {
    my($name, @data, %props) = (split ' ');
    @props{qw(Size Country Currency Temperature)} = @data;
    $name => \%props
} $string =~ m|
    ^/begin \s+ CITY
    (.+?)
    ^/end \s+ CITY
|gsmx;

print Dumper(\%cities);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...