包含来自不同文件 Perl 的列的文件
File containing columns from different files Perl
我想合并 2 个文件中的多列。
第一个文件例如:
Name Age
Bob 22
Carl 19
Daniel 29
Frank 31
Zach 22
第二个文件例如:(DANIEL 没有 GPA 值,所以我们将其留空)
Name GPA
Bob 3.0
Carl 3.5
Daniel
Frank 2.6
Zach 2.9
我想输出类似
的东西
Name Age GPA
Bob 22 3.0
Carl 19 3.5
Daniel 29
Frank 31 2.6
Zach 22 2.9
由于名称相同,我可以使用任一文件的第一列。
这是我目前的代码,但它没有输出任何东西。
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";
}
我该如何解决这个问题,以便它从第一个文件中获取第一列和第二列,并将第二个文件中的第二列附加到它上面? (我要的是姓名、年龄、GPA的顺序)
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 // "",
);
}
虽然我喜欢 perl...非 perl shell 一行:
$ 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
(需要 bash、zsh 或另一个理解 $'\t'
文字的 shell,以及 GNU 连接。还假设文件按照您的示例排序。)
我想合并 2 个文件中的多列。
第一个文件例如:
Name Age
Bob 22
Carl 19
Daniel 29
Frank 31
Zach 22
第二个文件例如:(DANIEL 没有 GPA 值,所以我们将其留空)
Name GPA
Bob 3.0
Carl 3.5
Daniel
Frank 2.6
Zach 2.9
我想输出类似
的东西Name Age GPA
Bob 22 3.0
Carl 19 3.5
Daniel 29
Frank 31 2.6
Zach 22 2.9
由于名称相同,我可以使用任一文件的第一列。
这是我目前的代码,但它没有输出任何东西。
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";
}
我该如何解决这个问题,以便它从第一个文件中获取第一列和第二列,并将第二个文件中的第二列附加到它上面? (我要的是姓名、年龄、GPA的顺序)
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 // "",
);
}
虽然我喜欢 perl...非 perl shell 一行:
$ 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
(需要 bash、zsh 或另一个理解 $'\t'
文字的 shell,以及 GNU 连接。还假设文件按照您的示例排序。)