Reputation: 542
I want to combine multiple columns from 2 files.
First File ex:
Name Age
Bob 22
Carl 19
Daniel 29
Frank 31
Zach 22
Second File ex: (THERE IS NO GPA VALUE FOR DANIEL SO WE LEAVE IT EMPTY)
Name GPA
Bob 3.0
Carl 3.5
Daniel
Frank 2.6
Zach 2.9
I want to ouput something that looks like
Name Age GPA
Bob 22 3.0
Carl 19 3.5
Daniel 29
Frank 31 2.6
Zach 22 2.9
Since the names are the same, I can use the first column of either file.
Here is the code I have so far, but it's not outputting anything.
unless (open COL1, '<'. $file1) {die "Couldn't open '$file1'\n";}
unless (open COL2, '<'. $file2) {die "Couldn't open '$file2'\n";}
my %feature;
my @files = (scalar <COL1>, scalar <COL2>);
for my $file (@files) {
open my $infh, '<', $file or die $!;
while (<$infh>) {
chomp;
my ($feature, $value) = split /\s+/, $_;
push @{$feature{$feature}}, $value;
}
}
close COL1;
close COL2;
foreach my $k (keys %feature) {
print "$k @{$feature{$k}}\n";
}
How can I fix this so that it takes the first and second column from the first file and appends the second column from the second file onto it? (I want it in the order of Name, Age, GPA).
Upvotes: 0
Views: 44
Reputation: 52364
Much as I like perl... non-perl shell one-liner:
$ join --header -t $'\t' file1.txt file2.txt
Name Age GPA
Bob 22 3.0
Carl 19 3.5
Daniel 29
Frank 31 2.6
Zach 22 2.9
(Does require bash, zsh, or another shell that understands $'\t'
literals, as well as GNU join. Also assumes the files are sorted like your example.)
Upvotes: 1
Reputation: 385789
use List::Util qw( max );
my %students;
{
open(my $fh, '<', $qfn1)
or die("Can't open \"$qfn1\": $!\n");
while (<$fh>) {
my ($name, $age) = split;
$students{$name}{age} = $age;
}
}
{
open(my $fh, '<', $qfn2)
or die("Can't open \"$qfn2\": $!\n");
while (<$fh>) {
my ($name, $gpa) = split;
$students{$name}{gpa} = $gpa;
}
}
my $max_name_len = max map length, "Name", keys %students;
my $max_age_len = max map length, "Age", grep defined, map $_->{age}, values %students;
my $max_gpa_len = max map length, "GPA", grep defined, map $_->{gpa}, values %students;
printf("%-*s %-*s %-*s\n",
$max_name_len, "Name",
$max_age_len, "Age",
$max_gpa_len, "GPA",
);
for my $name (sort keys %students) {
my $student = $students{$name};
my $age = $student->{age};
my $gpa = $student->{gpa};
printf("%-*s %*s %*s\n",
$max_name_len, $name,
$max_age_len, $age // "",
$max_gpa_len, $gpa // "",
);
}
Upvotes: 2