Perl - loading records from a file into a hash

Is it possible to load records from a file directly into a hash, please? Entries are shared with / begin and / end and have a fixed order of content.

I want the hash to be populated as follows:

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' 

Then I can leave and process the entries in the hash file, etc. (reason to write "slurped_record" later. I want to add new keys to say London, for example, "country = England", etc.

 hash_city{London}{Country}='England' 

I managed to achieve something that works by breaking out instead of reading the file in turn. Matching to / begin, creating a record ($ rec. = $ _), Then matching at / end and processing. It's a little messy and wondering if there was a more elegant approach to Perl.

My code attempt so far looks like this:

 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 
+4
source share
3 answers

Made a small program to show the other side, promoting your process. ) I do not know if he is elegant or not, but I believe that he is doing his job. )

 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 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; 
+3
source

Perhaps you can use the flip-flop operator : /FROM/ .. /TO/ . You can use a different delimiter to make the regex more readable. I am using m#^/begin ...# below. Retrieving the name of a city is simple assuming there are gaps between the title and the name of the city. I use \S (non-whitespace) since you donโ€™t want to skip city names with non-alphanumeric characters in the name, such as โ€œFoo-Barโ€ or โ€œSt.Tropezโ€.

If you find city names that contain spaces, you may need to find the best regular expression to find the city name. I will leave it as an exercise.

 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); 
+1
source

This will give you a hash with all the cities and their properties :

 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); 
0
source

Source: https://habr.com/ru/post/1398704/


All Articles