user3134370
user3134370

Reputation:

Perl : Unable to write output to file

So I have this code which takes input and output file from command line, then writes a certain output to the output file (Only the relevant portion shown here due to privacy issues):

use strict;
use warnings;
use autodie;

# check that two arguments have been passed
die "usage: $0 input output\n" unless @ARGV == 2;

my $infile  = shift;
my $outfile = shift;

open my $in, "<", $infile;
open(DATA, $in);
open my $out, ">", $outfile;

my %DEF = (
    I   => [ qw( P Pl P.P P.Pl Pl.P Pl.Pl P.P.P P.P.Pl P.Pl.P P.Pl.Pl Pl. +P.P Pl.P.Pl Pl.Pl.P Pl.Pl.Pl ) ],
    II  => [ qw( E P.E Pl.E P.P.E P.Pl.E Pl.P.E Pl.Pl.E ) ],
    III => [ qw( E.P E.Pl P.E.P P.E.Pl Pl.E.P Pl.E.Pl E.P.P E.P.Pl E.Pl.P + E.Pl.Pl ) ],
    IV  => [ qw( E.E P.E.E Pl.E.E E.P.E E.Pl.E E.E.P E.E.Pl E.E.E ) ]
);
# Hash table/dictionary for all the  groups

my @rank  = map @$_, @DEF{qw(I II III IV)};
my %rank  = map { $rank[$_ - 1] => $_ } 1 .. @rank;
my @group = map { ($_) x @{ $DEF{$_} } } qw(I II III IV);
my %group = map { $rank[$_ - 1] => $group[$_ - 1] . "_" . $_ } 1 .. @group;

sub rank {
  $rank{ $a->[2] } <=> $rank{ $b->[2] }
}

my %T;

sub oh {
  map values %$_, @_;
}

sub ab {
  my ($b, $a) = @_;
  [$b->[0], $a->[1], qq($a->[2].$b->[2]), qq($b->[3]<-$a->[3])];
}

sub xtend {
  my $a = shift;
  map { ab $_, $a } oh @{ $T{ $a->[0] } }{@_};
}

sub ins {
  $T{ $_[3] //= $_[1] }{ $_[2] }{ $_[0] } = \@_;
}

ins split /,\s*/ for <DATA>;

#ins split /,\s*/ for $filename;
ins @$_ for map { xtend $_, qw(P E Pl) } (oh oh oh \%T);
ins @$_ for map { xtend $_, qw(P E Pl) } (oh oh oh \%T);

for (sort { rank } grep { $_->[1] eq 'Q' } (oh oh oh \%T)) {

  print $out "%-4s: %20s,   %-8s %6s\n",
      $_->[0],
      qq($_->[0]$_->[3]),
      $_->[2],
      $group{ $_->[2] };

  close $in;
  close $out;
}

The problem is that it isnt writing anything to the output file.

perl program.pl input_file output_file

Due to certain reasons I want to read in the input file in format, so that cant be done away with.

Please help

input_file
M19,Q,P,
M31,M19,Pl,
M420,M31,E,
M421,M31,E,
M33,M31,E,
M438,M33,Pl,
M445,M33,E,
M437,M33,E,
M444,M33,E,
M73,M33,E,
M552,M73,Pl,
M553,M73,Pl,
M569,M73,E,
M549,M73,E,
M550,M73,E,

Upvotes: 1

Views: 169

Answers (1)

Borodin
Borodin

Reputation: 126762

The major problems I can see are these

  • The line open(DATA, $in) is meaningless. I presume you want to test your program with data from the DATA file handle, in which case you want

    my $in = \*DATA;
    
  • You are closing both file handles inside the final for loop. That means only one line will ever be written to the output, and thereafter you will get the warning

    print() on closed filehandle

  • You are using print with a format. You need printf instead

This variant of your program fixes these things, and produces some output. Is it what you expected?

use strict;
use warnings;
use autodie;

# check that two arguments have been passed
# die "usage: $0 input output\n" unless @ARGV == 2;

my ($infile, $outfile) = @ARGV;
# open my $in_fh,  '<', $infile;
# open my $out_fh, '>', $outfile;

my $in_fh  = \*DATA;
my $out_fh = \*STDOUT;

my %DEF = (
    I   => [ qw( P Pl P.P P.Pl Pl.P Pl.Pl P.P.P P.P.Pl P.Pl.P P.Pl.Pl Pl. +P.P Pl.P.Pl Pl.Pl.P Pl.Pl.Pl ) ],
    II  => [ qw( E P.E Pl.E P.P.E P.Pl.E Pl.P.E Pl.Pl.E ) ],
    III => [ qw( E.P E.Pl P.E.P P.E.Pl Pl.E.P Pl.E.Pl E.P.P E.P.Pl E.Pl.P + E.Pl.Pl ) ],
    IV  => [ qw( E.E P.E.E Pl.E.E E.P.E E.Pl.E E.E.P E.E.Pl E.E.E ) ]
);
# Hash table/dictionary for all the  groups

my @rank  = map { @$_ }  @DEF{qw(I II III IV)};
my %rank  = map { $rank[$_ - 1] => $_ }  1 .. @rank;
my @group = map { ($_) x @{ $DEF{$_} } }  qw(I II III IV);
my %group = map { $rank[$_ - 1] => $group[$_ - 1] . "_" . $_ }  1 .. @group;

my %T;

sub rank {
  $rank{ $a->[2] } <=> $rank{ $b->[2] }
}

sub oh {
  map values %$_, @_;
}

sub ab {
  my ($b, $a) = @_;
  [ $b->[0], $a->[1], qq($a->[2].$b->[2]), qq($b->[3]<-$a->[3]) ];
}

sub xtend {
  my $a = shift;
  map { ab $_, $a } oh @{ $T{ $a->[0] } }{@_};
}

sub ins {
  $T{ $_[3] //= $_[1] }{ $_[2] }{ $_[0] } = \@_;
}

ins split /,\s*/ for <$in_fh>;
close $in_fh;

ins @$_ for map { xtend $_, qw(P E Pl) } (oh oh oh \%T);
ins @$_ for map { xtend $_, qw(P E Pl) } (oh oh oh \%T);

for (sort { rank } grep { $_->[1] eq 'Q' } (oh oh oh \%T)) {

  printf $out_fh "%-4s: %20s,   %-8s %6s\n",
      $_->[0],
      qq($_->[0]$_->[3]),
      $_->[2],
      $group{ $_->[2] };
}

close $out_fh;

__DATA__
M19,Q,P,
M31,M19,Pl,
M420,M31,E,
M421,M31,E,
M33,M31,E,
M438,M33,Pl,
M445,M33,E,
M437,M33,E,
M444,M33,E,
M73,M33,E,
M552,M73,Pl,
M553,M73,Pl,
M569,M73,E,
M549,M73,E,
M550,M73,E,

output

M19 :                 M19Q,   P           I_1
M31 :            M31M19<-Q,   P.Pl        I_4
M421:      M421M31<-M19<-Q,   P.Pl.E    II_20
M420:      M420M31<-M19<-Q,   P.Pl.E    II_20
M33 :       M33M31<-M19<-Q,   P.Pl.E    II_20

Upvotes: 2

Related Questions