我正在尝试通过Perl合并两个文件。
到目前为止的代码:
my $hash_ref;
open (my $I_fh, "<", "File1.txt") or die $!;
my $line = <$I_fh>;
while ($line = <$I_fh>) {
chomp $line;
my @cols = split ("\t", $line);
my $key = $cols[1];
$hash_ref -> {$key} = \@cols;
}
close $I_fh;
open (my $O_fh, "<", "File2.txt") or die $!;
while ($line = <$O_fh>) {
chomp $line;
my @cols = split ("\t", $line);
my $key = shift (@cols);
push (@{$hash_ref -> {$key}}, @cols);
}
close $O_fh;
open (my $out, ">", "merged.txt") or die $!;
foreach my $key (sort keys %$hash_ref) {
my $row = join ("\t", @{$hash_ref -> {$key}});
print $out "$key\t$row\n";
}
close $out;
我正在使用打印或转储功能检查每个步骤。在终端窗口中,一切都很好。但是,在我的输出文件(合并的txt)中,格式已更改。我想通过添加更多列而不是添加更多行来合并两个文件。如何修复代码?
File 1.txt:
Index Name Column1 Column2
1 A1 AB
2 A2 CD
3 B1 EF
4 B2 GH
File 2.txt:
Name Type
A1 1
A2 1
B1 2
B2 1
Merged file:
A1 1 AB
1
A2 2 CD
1
B1 3 EF
2
B2 4 GH
1
Wanted file:
Name Type Column2
A1 1 AB
A2 1 CD
B1 2 EF
B2 1 GH
答案 0 :(得分:1)
假设文件是根据名称列进行排序的,这要归功于join(1)程序:
$ join --header -t $'\t' -o 2.1,2.2,1.4 -1 2 -2 1 file1.tsv file2.tsv
Name Type Column2
A1 1 AB
A2 1 CD
B1 2 EF
B2 1 GH
--header
选项是GNU扩展,它排除了两个文件的第一行之间的联接,而将它们视为列标题。 -t
设置列分隔符,-o
控制输出中包含哪些列(FILE.COLUMN指定符列表),-1
和-2
选择用于合并两个文件。
如果未对它们进行排序,或者如果您对perl进行了设置,则您的代码看起来非常接近;除了所有错别字外,您还将打印每一列,而不仅仅是您想要的输出所暗示的。考虑:
#!/usr/bin/perl
use warnings;
use strict;
use feature qw/say/;
use autodie;
my %names;
sub read_file {
my ($file, $idx) = @_;
open my $in, "<", $file;
my $header = <$in>;
while (<$in>) {
chomp;
my @F = split /\t/;
push @{$names{$F[$idx]}}, \@F;
}
}
read_file "file1.tsv", 1;
read_file "file2.tsv", 0;
say "Name\tType\tColumn2";
for my $n (sort keys %names) {
my $row = $names{$n};
say "$n\t$row->[1][1]\t$row->[0][3]";
}
我还怀疑,当您的操作系统使用Unix样式的行尾时,您的程序可能会在使用Windows样式的行尾的数据文件上运行,从而解释了您的奇怪输出。