文件1
A11;F1;BMW
A23;F2;BMW
B12;F3;BMW
H11;F4;JBW
文件2
P01;A1;0;0--00 ;123;456;150
P01;A11;0;0--00 ;123;444;208
P01;B12;0;0--00 ;123;111;36
P01;V11;0;0--00 ;123;787;33.9
输出
-;-;-;P01;A1;0;0--00 ;123;456;150
A11;F1;BMW;P01;A11;0;0--00 ;123;444;208
B12;F3;BMW;P01;B12;0;0--00 ;123;111;36
-;-;-;P01;V11;0;0--00 ;123;787;33.9
我试过
awk 'FNR==NR {a[$2] = $0; next }{ if($1 in a) {p=$1;$1="";print a[p],$0}}' File1 File2
但没有工作。
基本上我想从文件1中获取详细信息并与FILE2(主列表)进行比较。
示例:
FILE2中的A1在FILE1中不可用,因此在输出文件中,前三个字段为“ - ”,FILE2为休息。现在,我们有A11,我们得到了FILE1的细节。所以我们从文件1和文件中写下A11的详细信息。 2
答案 0 :(得分:5)
我个人会在Perl中这样做,但由于每个人和他们的母亲都给你一个Perl解决方案,这里有一个替代方案:
如果每个文件中的记录具有一致的字段数,并且假设每个文件中的记录按字典顺序中的“join”字段排序,则可以使用join
:
join -1 1 -2 2 -t ';' -e - -o '1.1 1.2 1.3 2.1 2.2 2.3 2.4 2.5 2.6 2.7' -a 2 File1 File2
选项说明:
-1 1
和-2 2
表示“加入”字段(A11
,A23
等)是File1
中的第一个字段,第二个字段File2
中的字段。-t ';'
表示字段由;
-e -
表示空字段应替换为-
-o '1.1 1.2 1.3 2.1 2.2 2.3 2.4 2.5 2.6 2.7'
表示您希望每个输出行都包含File1
中的前三个字段,后跟File2
中的前七个字段。 (这就是为什么这种方法要求每个文件中的记录具有一致数量的字段。)-a 2
表示您希望在输出中包含File2
中的每一行,即使File1
没有相应的行。 (否则它只会输出两个文件中都匹配的行。)答案 1 :(得分:3)
通常的Perl方式:使用哈希来记住主列表:
#!/usr/bin/perl
use warnings;
use strict;
my %hash;
open my $MASTER, '<', 'File1' or die $!;
while (<$MASTER>) {
chomp;
my @columns = split /;/;
$hash{$columns[0]} = [@columns[1 .. $#columns]];
}
close $MASTER;
open my $DETAIL, '<', 'File2' or die $!;
while (<$DETAIL>) {
my @columns = split /;/;
if (exists $hash{$columns[1]}) {
print join ';', $columns[1], @{ $hash{$columns[1]} }, q();
} else {
print '-;-;-;';
}
print;
}
close $DETAIL;
答案 2 :(得分:2)
使用Perl:
use warnings;
use strict;
my %file1;
open (my $f1, "<", "file1") or die();
while (<$f1>) {
chomp;
my @v = (split(/;/))[0];
$file1{$v[0]} = $_;
}
close ($f1);
open (my $f2, "<", "file2") or die();
while (<$f2>) {
chomp;
my $v = (split(/;/))[1];
if (defined $file1{$v}) {
print "$file1{$v};$_\n";
} else {
print "-;-;-;$_\n";
}
}
close ($f2);
答案 3 :(得分:1)
这不能在一行程序中方便地完成,因为它涉及读取两个输入文件,但问题并不困难
该程序从file1
读取所有行,并使用第一个字段作为键将行存储在散列中
然后读取file2
中的所有行,并将第二个字段用作访问散列的键。 //
defined-or运算符用于打印元素的值(如果存在)或默认字符串(如果不存在)
最后打印file2
的当前行
use strict;
use warnings;
my %data;
open my $fh, '<', 'file1' or die $!;
while (<$fh>) {
chomp;
my $key = (split /;/)[0];
$data{$key} = $_;
}
open $fh, '<', 'file2' or die $!;
while (<$fh>) {
my $key = (split /;/)[1];
print $data{$key} // '-;-;-;', $_;
}
<强>输出强>
-;-;-;P01;A1;0;0--00 ;123;456;150
A11;F1;BMWP01;A11;0;0--00 ;123;444;208
B12;F3;BMWP01;B12;0;0--00 ;123;111;36
-;-;-;P01;V11;0;0--00 ;123;787;33.9
答案 4 :(得分:1)
perl解决方案可能包含非常好的模块Text::CSV。如果是这样,您可以将值提取到散列中,然后使用该散列进行查找。查找值时,您将为查找散列中的任何未定义值插入空值-;-;-;
。
use strict;
use warnings;
use Text::CSV;
my $lookup = "file1.csv"; # whatever file is used to look up fields 0-2
my $master = "file2.csv"; # the file controlling the printing
my $csv = Text::CSV->new({
sep_char => ";",
eol => $/, # to add newline to $csv->print()
quote_space => 0, # to avoid adding quotes
});
my %lookup;
open my $fh, "<", $lookup or die $!;
while (my $row = $csv->getline($fh)) {
$lookup{$row->[0]} = $row; # add entire row to specific key
}
open $fh, "<", $master or die $!; # new $fh needs no close
while (my $row = $csv->getline($fh)) {
my $extra = $lookup{$row->[1]} // [ qw(- - -) ]; # blank row if undef
unshift @$row, @$extra; # add the new values
$csv->print(*STDOUT, $row); # then print them
}
<强>输出:强>
-;-;-;P01;A1;0;0--00 ;123;456;150
A11;F1;BMW;P01;A11;0;0--00 ;123;444;208
B12;F3;BMW;P01;B12;0;0--00 ;123;111;36
-;-;-;P01;V11;0;0--00 ;123;787;33.9