Hi,
Hello,
I have a simple code that take currently fixed to take 3 input files and append each line of these files together.
I wish to know is there anyway I can write the code more flexibly so it can dynamically take the input argument - from minimum 2 files to more.
Is there anywhere I can find information about dealing with this matter? Any specific module that cater this problem?
You could use the paste program to do that.
man paste
This is my current (terribly inefficient and unflexible) code:
#!/usr/bin/perl -w use strict; use Data::Dumper;
if(scalar @ARGV ne 1)
You are using 'ne' which compares strings when you should be using '!=' which is used to compare numbers. Both the comparison operator and the if conditional force scalar context so using 'scalar' is redundant.
if ( @ARGV != 1 )
However that only works if the command line has exactly one filename and you want to require two or more.
if ( @ARGV >= 2 )
{ print "Usage: $0 file1 file2 [file3] etc\n"; exit(1); } #the above part doesn't seem to be working well/useful
my $file1 = $ARGV[0]; my @set1 = get_file_data("$file1");
^^^^^^^^ perldoc -q quoting
Found in /usr/lib/perl5/5.8.2/pod/perlfaq4.pod What's wrong with always quoting "$vars"?
#Remove the whitspace and \n from each lines @set1 = grep { s/^\s+//; s/\s+$//; s/\s+/ /g; length } @set1; my $s1 = [EMAIL PROTECTED];
my $file2 = $ARGV[1]; my @set2 = get_file_data("$file2"); @set2 = grep { s/^\s+//; s/\s+$//; s/\s+/ /g; length } @set2; my $s2 = [EMAIL PROTECTED];
my $file3 = $ARGV[2]; my @set3 = get_file_data("$file3"); @set3 = grep { s/^\s+//; s/\s+$//; s/\s+/ /g; length } @set3; my $s3 = [EMAIL PROTECTED];
#Printout the appended lines from the data print map { join("",$set1[$_],$set2[$_],$set3[$_]), "\n" } (0..$#set1);
#Subroutine sub get_file_data {
my ($filename) = @_;
use strict; use warnings;
use() keeps track of which modules have been loaded so use()ing the same module more than once will not incur more overhead and will not do anything useful either.
# Initialize variables my @filedata = ();
my() creates a lexical variable in an undefined state so assigning an undefined value to it is redundant.
unless ( open( GET_FILE_DATA, $filename ) ) { print STDERR "Cannot open file \"$filename\"\n\n";
You should include the $! (or $^E) variable in the error message so you know why open() failed.
exit; }
@filedata = <GET_FILE_DATA>; close GET_FILE_DATA; return (@filedata);
If you had used a lexical filehandle you could have skipped the assignment to an array.
}
___END____
A valid __END__ token has two underscore characters before and after 'END'.
You have two basic options for merging files, store all the contents in memory which may run out of memory, or read each file line by line which may run out of file handles.
If the aggregate data will fit in memory you can do this:
#!/usr/bin/perl use warnings; use strict;
my ( $line, @data ); while ( <> ) { $data[ $line++ ] .= $_ if /\S/; $line = 0 if eof; }
# clean up whitespace for ( @data ) { s/^\s+//; s/\s+/ /g; s/ $/\n/; }
print @data;
__END__
And if you need to read each file a line at a time you could do something like this:
#!/usr/bin/perl use warnings; use strict;
my @fhs = map { open my $fh, '<', $_ or die "$_: $!"; $fh } @ARGV;
while ( @fhs ) { my $line = ''; for ( @fhs ) { defined( my $curr = <$_> ) or next; redo unless $curr =~ /\S/; $line .= $curr; }
for ( $line ) { s/^\s+//; s/\s+/ /g; s/ $/\n/; }
print $line; @fhs = grep !eof( $_ ), @fhs; }
__END__
John -- use Perl; program fulfillment
-- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] <http://learn.perl.org/> <http://learn.perl.org/first-response>