简体   繁体   English

包含来自不同文件Perl的列的文件

[英]File containing columns from different files Perl

I want to combine multiple columns from 2 files. 我想合并2个文件中的多个列。

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) 之前的第二个文件:(DANIEL没有GPA值,因此我们可以清空)

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). (我要按姓名,年龄,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 // "",
    );
}

Much as I like perl... non-perl shell one-liner: 我非常喜欢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

(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.) (需要bash,zsh或其他能够理解$'\\t'文字以及GNU连接的shell。还要假设文件的排序方式与您的示例相同。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM