Angharad has asked for the wisdom of the Perl Monks concerning the following question:
I have a number of files with data that is presented like this (only much larger).
1 G
2 F
4 H
8 T
5 Y
6 R
7 E
8 I
2 H
4 T
3 G
8 R
I would like to create a new file containing all the information in these files and format it as follows.
1 G 5 Y 2 H
2 F 6 R 4 T
4 H 7 E 3 G
8 T 8 I 8 R
Could someone please give me a few pointers as to how to do this? I guess I could open all the files, store them in separate hashes and then print them out somehow?
Thanks in advance
Re: making 3 files into one
by ikegami (Patriarch) on Feb 17, 2009 at 17:45 UTC
|
Is the relation between "1 G" and "5 Y" simply the position in the file? Then
my @qfns;
my @fhs;
for my $qfn (@qfns) {
open(my $fh, '<', $qfn)
or die("Can't open \"$qfn\": $!\n");
push @fhs, $fh;
}
for (;;) {
my @lines;
my $all_done = 1;
my $some_done = 0;
for my $fh (@fhs) {
push @lines, my $line = <$fh>;
if (defined($line)) { $some_done = 1; }
else { $all_done = 0; }
}
exit(0) if $all_done;
die("Premature eof\n") if $some_done;
chomp @lines;
print(join(' ', @lines), "\n");
}
| [reply] [d/l] |
Re: making 3 files into one
by toolic (Bishop) on Feb 17, 2009 at 17:45 UTC
|
If on unix, you could use paste:
paste file1 file2 file3 > file.out
| [reply] [d/l] |
Re: making 3 files into one
by Lawliet (Curate) on Feb 17, 2009 at 17:43 UTC
|
I would open each file and store them in separate arrays where each element of an array is a single line in the corresponding file. Open a fourth file for writing and use a for loop to print each element of each array.
for (my $i = 0; $i < $#file; $i++) {
print FILE "$file[$i] $file2[$i] $file3[$i]\n";
}
Or something~
And you didn't even know bears could type.
| [reply] [d/l] |
Re: making 3 files into one
by CountZero (Bishop) on Feb 17, 2009 at 22:26 UTC
|
Will handle arbitrarily large files with minimal memory use:
use strict;
open my $FILE1, '<', 'my/input/file1' or die "Could not open FILE1: $!
+";
open my $FILE2, '<', 'my/input/file2' or die "Could not open FILE2: $!
+";
open my $FILE3, '<', 'my/input/file3' or die "Could not open FILE3: $!
+";;
open my $FILE4, '>', 'my/output/file' or die "Could not open FILE4: $!
+";
while (my $file1 = <$FILE1>) {
my $file2 = <$FILE2>;
my $file3 = <$FILE3>;
chomp $file1;
chomp $file2;
print $FILE4, "$file1 $file2 $file3" or die "Could not print to FI
+LE4";
}
Update: We assume that each file has the same number of lines.
CountZero A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James
| [reply] [d/l] |
Re: making 3 files into one
by skywalker (Beadle) on Feb 17, 2009 at 18:05 UTC
|
Why dont you slurp each file into any array then use a for loop to print 1 record from each file at a time
quick bit of code
use strict;
my @file1 = ("1 G","2 F","4 H","8 T");
my @file2 = ("5 Y","6 R","7 E","8 I");
my @file3 = ("2 H","4 T","3 G","8 R");
my $largest_array = scalar @file1;
$largest_array = scalar @file2 if(scalar @file2 > $largest_array);
$largest_array = scalar @file3 if(scalar @file3 > $largest_array);
my @array =(\@file1,\@file2,\@file3);
for (my $ctr =0;$ctr <= $largest_array;$ctr++){
print $array[0][$ctr] if($ctr <= scalar @{$array[0]});
print $array[1][$ctr] if($ctr <= scalar @{$array[1]});
print $array[2][$ctr] if($ctr <= scalar @{$array[2]});
print "\n";
}
print "\n\nComplete";
| [reply] [d/l] |
Re: making 3 files into one
by GrandFather (Saint) on Feb 18, 2009 at 03:30 UTC
|
use strict;
use warnings;
my $file1 = <<'END_FILE';
1 G
2 F
4 H
8 T
END_FILE
my $file2 = <<'END_FILE';
5 Y
6 R
7 E
8 I
END_FILE
my $file3 = <<'END_FILE';
2 H
4 T
3 G
8 R
END_FILE
my @fileHandles;
open $fileHandles[@fileHandles], '<', $_ for \$file1, \$file2, \$file3
+;
printLines (@fileHandles);
close $_ for @fileHandles;
sub printLines {
my @fileHandles = @_;
my $moreLines = 1;
while ($moreLines) {
my $line = '';
for my $fh (@fileHandles) {
$line .= ' ' if length $line;
$line .= <$fh> or return;
chomp $line;
}
print "$line\n";
$line = '';
}
}
Prints:
1 G 5 Y 2 H
2 F 6 R 4 T
4 H 7 E 3 G
8 T 8 I 8 R
True laziness is hard work
| [reply] [d/l] [select] |
Re: making 3 files into one
by Anonymous Monk on Feb 18, 2009 at 08:49 UTC
|
hi friend,
Try out this one...
opendir(DIR,'.') or die $!;
@read=readdir(DIR);
close(DIR);
foreach(@read){
if($_ =~/^f\d.txt$/){
push(@read1,$_);
}
}
@read2=sort(@read1);
foreach (@read2){
open(FILE,$_) or die $!;
push(@file,<FILE>);
close(FILE);
push(@file,"LINE\n");
}
$string=join('',@file);
$string=~s/\n/#/g;
($val1,$val2,$val3)=split('LINE#',$string);
@val1=split('#',$val1);
@val2=split('#',$val2);
@val3=split('#',$val3);
foreach $i(0 .. scalar @val1){
print "$val1[$i]\t$val2[$i]\t$val3[$i]\n";
}
| [reply] [d/l] |
|
|