Extraction and printing of key-value pair from a t

2019-07-08 05:20发布

问题:

I have a text file temp.txt which contains entries like,

cinterim=3534
cstart=517
cstop=622
ointerim=47
ostart=19
ostop=20

Note: key-value pairs may be arranged in new line or all at once in one line separated by space.

I am trying to print and store these values in DB for corresponding keys using Perl. But I am getting many errors and warnings. Right now I am just trying to print those values.

use strict;
use warnings;

open(FILE,"/root/temp.txt") or die "Unable to open file:$!\n";

while (my $line = <FILE>) {
  # optional whitespace, KEY, optional whitespace, required ':', 
  # optional whitespace, VALUE, required whitespace, required '.'
  $line =~ m/^\s*(\S+)\s*:\s*(.*)\s+\./;
  my @pairs = split(/\s+/,$line);
  my %hash = map { split(/=/, $_, 2) } @pairs;

  printf "%s,%s,%s\n", $hash{cinterim}, $hash{cstart}, $hash{cstop};

}
close(FILE);

Could somebody provide help to refine my program.

回答1:

use strict;
use warnings;

open my $fh, '<', '/root/temp.txt' or die "Unable to open file:$!\n";
my %hash = map { split /=|\s+/; } <$fh>;
close $fh;
print "$_ => $hash{$_}\n" for keys %hash;

What this code does:

<$fh> reads a line from our file, or in list context, all lines and returns them as an array.

Inside map we split our line into an array using the regexp /= | \s+/x. This means: split when you see a = or a sequence of whitespace characters. This is just a condensed and beautified form of your original code.

Then, we cast the list resulting from map to the hash type. We can do that because the item count of the list is even. (Input like key key=value or key=value=valuewill throw an error at this point).

After that, we print the hash out. In Perl, we can interpolate hash values inside strings directly and don't have to use printf and friends except for special formatting.

The for loop iterates over all keys (returned in the $_ special variable), and $hash{$_} is the corresponding value. This could also have been written as

while (my ($key, $val) = each %hash) {
  print "$key => $val\n";
}

where each iterates over all key-value pairs.



回答2:

Try this

use warnings;

my %data = ();

open FILE, '<', 'file1.txt' or die $!;
while(<FILE>)
{
    chomp;
    $data{$1} = $2 while /\s*(\S+)=(\S+)/g;
}
close FILE;

print $_, '-', $data{$_}, $/ for keys %data;


回答3:

The simplest way is to slurp the entire file into memory and assign key/value pairs to the hash using a regular expression.

This program shows the technique

use strict;
use warnings;

my %data = do {
  open my $fh, '<', '/root/temp.txt' or die $!;
  local $/;
  <$fh> =~ /(\w+)\s*=\s*(\w+)/g;
};

use Data::Dump;
dd \%data;

output

{
  cinterim => 3534,
  cstart   => 517,
  cstop    => 622,
  ointerim => 47,
  ostart   => 19,
  ostop    => 20,
}