Reputation: 3
Actually in this assignment, I need to combine 12 input file datas into only one output file. Each input file like this,
ACME A 0 2
ACME A 1 0
ACME A 2 0
ACME A 3 0
ACME A 4 0
ACME A 5 0
ACME A 6 0
In output file ı want to obtain, all related data like this;
**********************************************************************
2017-02-03 0 ACME A 0 2 4 43 4 4 25 4 3 26 4 4 18
2017-02-03 0 ACME A 0 2 4 43 4 4 25 4 3 26 4 4 0
2017-02-03 0 ACME A 0 2 4 43 4 4 25 4 3 26 4 4 0
2017-02-03 0 ACME A 0 2 4 43 4 4 25 4 3 26 4 4 1
Here is my full code.
#! /usr/bin/perl -w
#compiler profilleri
use strict;
use warnings;
sub trim($)
{
my $string = shift;
$string =~ s/^\s+//;
$string =~ s/\s+$//;
return $string;
}
#dosya locationları
my $input_file="C:/Perl64/output/sbc_cause_comp_intraday_2017-02-03_00_01.txt";
my $input_file1="C:/Perl64/output/sbc_cause_comp_intraday_2017-02-03_00_06.txt";
my $input_file2="C:/Perl64/output/sbc_cause_comp_intraday_2017-02-03_00_11.txt";
my $input_file3="C:/Perl64/output/sbc_cause_comp_intraday_2017-02-03_00_16.txt";
my $input_file4="C:/Perl64/output/sbc_cause_comp_intraday_2017-02-03_00_21.txt";
my $input_file5="C:/Perl64/output/sbc_cause_comp_intraday_2017-02-03_00_26.txt";
my $input_file6="C:/Perl64/output/sbc_cause_comp_intraday_2017-02-03_00_31.txt";
my $input_file7="C:/Perl64/output/sbc_cause_comp_intraday_2017-02-03_00_36.txt";
my $input_file8="C:/Perl64/output/sbc_cause_comp_intraday_2017-02-03_00_41.txt";
my $input_file9="C:/Perl64/output/sbc_cause_comp_intraday_2017-02-03_00_46.txt";
my $input_file10="C:/Perl64/output/sbc_cause_comp_intraday_2017-02-03_00_51.txt";
my $input_file11="C:/Perl64/output/sbc_cause_comp_intraday_2017-02-03_00_56.txt";
my $output_file="C:/Perl64/output/denemecik.txt";
#komutlar######
my $ne; my @cc_type; my @cc_count;
my @cc_count1; my @cc_count2; my @cc_count3; my @cc_count4; my @cc_count5;
my @cc_count6; my @cc_count7; my @cc_count8; my @cc_count9; my @cc_count10; my @cc_count11;
my @total; my $i;
my @count=0; my @count1=0; my @count2=0; my @count3=0; my @count4=0; my @count5=0; my @count6=0;
my @count7=0; my @count8=0; my @count9=0; my @count10=0; my @count11=0;
my $date='sbc_cause_comp_intraday_2017-02-03_00_01';
my $date1=substr($date,24,10);
my $hour=substr($date,35,1);
#print ($hour);
open INPUT, "< $input_file" or die "$0: open of $input_file failed, error: $! \n";
open INPUT1, "< $input_file1" or die "$0: open of $input_file1 failed, error: $! \n";
open INPUT2, "< $input_file2" or die "$0: open of $input_file2 failed, error: $! \n";
open INPUT3, "< $input_file3" or die "$0: open of $input_file3 failed, error: $! \n";
open INPUT4, "< $input_file4" or die "$0: open of $input_file4 failed, error: $! \n";
open INPUT5, "< $input_file5" or die "$0: open of $input_file5 failed, error: $! \n";
open INPUT6, "< $input_file6" or die "$0: open of $input_file6 failed, error: $! \n";
open INPUT7, "< $input_file7" or die "$0: open of $input_file7 failed, error: $! \n";
open INPUT8, "< $input_file8" or die "$0: open of $input_file8 failed, error: $! \n";
open INPUT9, "< $input_file9" or die "$0: open of $input_file9 failed, error: $! \n";
open INPUT10, "< $input_file10" or die "$0: open of $input_file10 failed, error: $! \n";
open INPUT11, "< $input_file11" or die "$0: open of $input_file11 failed, error: $! \n";
open OUTPUT, "> $output_file" or die "$0: open of $output_file failed, error: $! \n";
print OUTPUT ("**********************************************************************\n");
while ( defined ($_=<INPUT>) )
{
my $line = $_;
my ( $ne, $cc_type, $cc_count) = split ('\t',$line);
my $count=trim($cc_count);
print("$ne\n");
while ( defined ($_=<INPUT1>) )
{
my $line1 = $_;
my ( undef, undef, $cc_count1) = split ('\t',$line1);
my $count1=trim($cc_count1);
#print("$count1\n");
while ( defined ($_=<INPUT2>) )
{
my $line2 = $_;
my ( undef, undef, $cc_count2) = split ('\t',$line2);
my $count2=trim($cc_count2);
#print("$cc_count2\n");
while ( defined ($_=<INPUT3>) )
{
my $line3 = $_;
my ( undef, undef, $cc_count3) = split ('\t',$line3);
my $count3=trim($cc_count3);
#print("$cc_count3\n");
while ( defined ($_=<INPUT4>) )
{
my $line4 = $_;
my ( undef, undef, $cc_count4) = split ('\t',$line4);
my $count4=trim($cc_count4);
# print("$cc_count4\n");
while ( defined ($_=<INPUT5>) )
{
my $line5 = $_;
my ( undef, undef, $cc_count5) = split ('\t',$line5);
my $count5=trim($cc_count5);
#print("$cc_count5\n");
while ( defined ($_=<INPUT6>) )
{
my $line6 = $_;
my ( undef, undef, $cc_count6) = split ('\t',$line6);
my $count6=trim($cc_count6);
#print("$cc_count6\n");
while ( defined ($_=<INPUT7>) )
{
my $line7 = $_;
my ( undef, undef, $cc_count7) = split ('\t',$line7);
my $count7=trim($cc_count7);
#print("$cc_count7\n");
while ( defined ($_=<INPUT8>) )
{
my $line8 = $_;
my ( undef, undef, $cc_count8) = split ('\t',$line8);
my $count8=trim($cc_count8);
#print("$cc_count8\n");
while ( defined ($_=<INPUT9>) )
{
my $line9 = $_;
my ( undef, undef, $cc_count9) = split ('\t',$line9);
my $count9=trim($cc_count9);
#print("$cc_count9\n");
while ( defined ($_=<INPUT10>) )
{
my $line10 = $_;
my ( undef, undef, $cc_count10) = split ('\t',$line10);
my $count10=trim($cc_count10);
#print("$cc_count10\n");
while ( defined ($_=<INPUT11>) )
{
my $line11 = $_;
my ( undef, undef, $cc_count11) = split ('\t',$line11);
my $count11=trim($cc_count11);
#print("$cc_count11\n");
for( $i=0; $i< scalar @count; $i++ )
{
$total[$i] = $count[$i] + $count1[$i] + $count2[$i] + $count3[$i] + $count4[$i] + $count5[$i] + $count6[$i] + $count7[$i] + $count8[$i] + $count9[$i] + $count10[$i] + $count11[$i];
# print("@total\n");
}
print OUTPUT ("$date1 $hour $ne $cc_type $count $count1 $count2 $count3 $count4 $count5 $count6 $count7 $count8 $count9 $count10 $count11 $total\n");
# print("@total\n");
}
}
}
}
}
}
}
}
}
}
}
}
close OUTPUT;
close INPUT;
close INPUT1;
close INPUT2;
close INPUT3;
close INPUT4;
close INPUT5;
close INPUT6;
close INPUT7;
close INPUT8;
close INPUT9;
close INPUT10;
close INPUT11;
I am a newbie in perl. Can you please help me to write this code more logically. For example how can ı read multiple input files without using a lot of while loop and writing into only one output file. Right now, output file shows only first row as true, and the remaining rows just the iteration of the first one, so it is not true. The second problem is,I dont know how to add number values in one row properly. For example I want to add 2 to 18 ( 12 values) and write this value as a final column in output file. Thanks in advance.
Upvotes: 0
Views: 94
Reputation: 385789
sub sum { my $sum; $sum += $_ for @_; $sum }
my $sum = sum
@count,
@count1,
...
@count10,
@count11;
Rather than having a ton of arrays, you should probably have an array of arrays (or hash of arrays).
sub sum { my $sum; $sum += $_ for @_; $sum }
while (<>) {
chomp;
my @fields = split /\t/;
push @aoa, \@fields;
}
my $sum = sum map { @$_[4..15] } @aoa;
or just
my $sum;
while (<>) {
chomp;
my @fields = split /\t/;
$sum += $_ for @fields[4..15];
}
(There appears to be 17 columns, yet you say there are 16, so I'm assuming the whitespace beteween ACME A
isn't a tab. Adjust the indexes as needed.)
Upvotes: 2
Reputation: 126722
This solution reads the input file and splits each line, storing the result as an array of arrays. A pair of map
calls reduces that data to an array of column totals
There is clearly an issue with some of the data not being numeric, so each column is tested to see if it contains any non-numeric values, in which case undef
is provided as the total
I have used first
from List::Util
even though all
would be clearer because it is only more recent versions of the module that provide the latter
I have tested this by creating a file with two copies of your line of data. (Please provide a more comprehensive data sample in the future.)
The program expects the path to the input file as a parameter on the command line
I have used Data::Dumper
only to reveal the result of the calculation
use strict;
use warnings 'all';
use List::Util qw/ first sum /;
use Scalar::Util qw/ looks_like_number /;
our @ARGV = 'data.txt';
my @data = map [ split ], <>;
my @totals = map {
my $i = $_;
my @column = map { $_->[$i] } @data;
defined( first { not looks_like_number($_) } @column) ? undef : sum(@column);
} 0.. $#{$data[0]};
use Data::Dumper;
print Dumper \@totals;
If you are using a more recent copy of List::Util
that provided all
, then you can make use of it by changing the use
statement to
use List::Util qw/ all sum /;
and rewriting the defined( ... )
line to
all { looks_like_number($_) } @column ? sum(@column) : undef;
$VAR1 = [
undef,
'0',
undef,
undef,
'0',
'4',
'8',
'86',
'8',
'8',
'50',
'8',
'6',
'52',
'8',
'8',
'36'
];
Upvotes: 1
Reputation: 53478
OK, any point you start numbering variables, you should be seriously thinking about using an array instead.
And that goes if they're arrays too. So you might be able to use an array of arrays, but it's unclear quite what you're actually putting into $count
.
But for your problem, I'd tackle it like this:
#!/usr/bin/env perl
use strict;
use warnings;
#iterate the DATA filehandle below, line by line.
while ( <DATA> ) {
#split the row on whitespace.
my @row = split;
my $sum;
#iterate each field
foreach my $value ( @row ) {
#increment the sum by the value, if it's numeric.
if ( $value =~ m/^\d+$/ ) {
$sum += $value;
}
}
#print the sum for this row.
print $sum,"\n";
}
__DATA__
2017-02-03 0 ACME A 0 2 4 43 4 4 25 4 3 26 4 4 18
And that way, you don't actually need an array of arrays at all.
Note - you can scale this up to your input, probably by just using <>
as your input file handle, which reads files specified on command line or STDIN rather than the __DATA__
filehandle.
Upvotes: 4
Reputation: 118128
The script below will sum all numeric columns in the data individually and put the sums in an hash called %counts
. The keys of the hash will be variable names (which I would normally infer from the header of the file, but you do not provide it, so I made them up).
#!/usr/bin/env perl
use strict;
use warnings;
use List::Util qw( sum );
my %counts;
while (my $line = <DATA>) {
my (@cols) = split ' ', $line;
my @numeric = map [$_, $cols[$_]], grep $cols[$_] =~ /^[0-9]+\z/, 0 .. $#cols;
for my $entry ( @numeric ) {
$counts{ 'VAR' . $entry->[0] } += $entry->[1];
}
}
use Data::Dumper;
print Dumper \%counts;
printf "Grand total = %d\n", sum values %counts;
__DATA__
2017-02-03 0 ACME A 0 2 4 43 4 4 25 4 3 26 4 4 18
2017-02-03 0 ACME A 0 2 4 43 4 4 25 4 3 26 4 4 18
2017-02-03 0 ACME A 0 2 4 43 4 4 25 4 3 26 4 4 18
2017-02-03 0 ACME A 0 2 4 43 4 4 25 4 3 26 4 4 18
2017-02-03 0 ACME A 0 2 4 43 4 4 25 4 3 26 4 4 18
Output:
$ perl s.pl $VAR1 = { 'VAR7' => 215, 'VAR15' => 20, 'VAR8' => 20, 'VAR11' => 20, 'VAR14' => 20, 'VAR10' => 125, 'VAR12' => 15, 'VAR1' => 0, 'VAR4' => 0, 'VAR5' => 10, 'VAR6' => 20, 'VAR9' => 20, 'VAR16' => 90, 'VAR13' => 130 }; Grand total = 705
Upvotes: 2