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";
}
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
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.