Frage

i have a text file which looks like this.

    Parameter 0:
    Field 1           : 100
    Field 2           : 0
    Field 3           : 4

    Parameter 1:
    Field 1           : 873
    Field 2           : 23
    Field 3           : 89

I want to write a perl script that parses this file in the following format

     Parameter Field1 Field2 Field3
       0          100     0      4
       1          873     23     89

Can anyone help me with this. Any help will be greatly appreciated. i have tried the following so far

my %hash = ();
my $file = "sample.txt";

open (my $fh, "<", $file) or die "Can't open the file $file: ";

while (my $line =<$fh>)
{
    chomp ($line);
    my($key) = split(" : ", $line);
    $hash{$key} = 1;
}

foreach my $key (sort keys %hash)
{
    print "$key\n";
}
War es hilfreich?

Lösung

This Perl program does what you ask. It allows for any number of fields for each parameter (although there must be the same number of fields for every parameter) and takes the header labels for the fields from the data itself.

use strict;
use warnings;

my $file = 'sample.txt';

open my $fh, '<', $file or die qq{Can't open "$file" for input: $!};

my %data;
my @params;
my @fields;

while (<$fh>) {
  next unless /\S/;
  chomp;

  my ($key, $val) = split /\s*:\s*/;
  if ($val =~ /\S/) {
    push @fields, $key if @params == 1;
    push @{ $data{$params[-1]} }, $val if @params;
  }
  else {
    die qq{Unexpected parameter format "$key"} unless $key =~ /parameter\s+(\d+)/i;
    push @params, $1;
  }
}

my @headers = ('Parameter', @fields);
my @widths = map length, @headers;
my $format = join(' ', map "%${_}s", @widths) . "\n";

printf $format, @headers;
for my $param (@params) {
  printf $format, $param, @{ $data{$param} };
}

output

Parameter Field 1 Field 2 Field 3
        0     100       0       4
        1     873      23      89

Andere Tipps

use warnings; use strict;

my $file = "sample.txt";
open (my $fh, "<", $file) or die "Can't open the file $file: ";

print "Parameter Field1 Field2 Field3\n";

while (my $line=<$fh>) {

  process_parameter($1) if $line =~ /Parameter (\d+):/;

}

sub process_parameter {

  my $parameter = shift;

  my ($field_1) = (<$fh> =~ /(\d+) *$/);
  my ($field_2) = (<$fh> =~ /(\d+) *$/);
  my ($field_3) = (<$fh> =~ /(\d+) *$/);

  printf "  %-2d         %-6d  %-6d %-6d\n", $parameter, $field_1, $field_2, $field_3;
}
#!/usr/bin/perl

my %hash = ();
my %fields;

my $param;

while ( chomp( my $line = <DATA> ) ) {
    if ( $line =~ /Parameter (\d+):/ ) {
        $param = $1;
    }
    next unless ( defined $param );

    if ( my ( $f, $v ) = $line =~ /(Field \d+)[\s\t]*: (\d+)/ ) {
        $hash{$param} ||= {};

        $hash{$param}->{$f} = $v;

        $fields{$f} ||= 1;
    }

}

my @fields = sort keys %fields;
print join( ',', 'Parameter', @fields ), "\n";

foreach my $param ( sort { $a <=> $b } keys %hash ) {
    print join( ',', $param, @{ $hash{$param} }{@fields} ), "\n";
}

__DATA__
Parameter 0:
Field 1           : 100
Field 2           : 0
Field 3           : 4

Parameter 1:
Field 1           : 873
Field 2           : 23
Field 3           : 89

Here is a way that accepts any number of fields for each parameter:

my $par;
my %out;
my $max = 0;
while(<DATA>) {
    chomp;
    next if /^\s*$/;
    if (/Parameter\s*(\d+)/) {
        $par = $1;
        next;
    }
    my ($k, $v) = $_ =~/Field\s+(\d+)\s*:\s*(\d+)/;
    $out{$par}[$k] = $v;
    $max = $k if $k > $max;
}
my $cols = 'Param';
$cols .= "\tField $_" for (1..$max);
say $cols;
foreach my $par(sort (keys %out))  {
    my $out = $par;
    $out .= "\t".($out{$par}[$_]//' ') for (1..$max);
    say $out;
}

__DATA__
Parameter 0:
    Field 1           : 100
    Field 2           : 0
    Field 3           : 4
    Field 5 :18

    Parameter 1:
    Field 1           : 873
    Field 2           : 23
    Field 3           : 89
    Field 4     : 123

output:

Param   Field 1 Field 2 Field 3 Field 4 Field 5
0       100     0       4               18
1       873     23      89      123 
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top