![根据键比较两个文件,在 Bash Shell 脚本中打印另一个文件中值的差异](https://linux22.com/image/171249/%E6%A0%B9%E6%8D%AE%E9%94%AE%E6%AF%94%E8%BE%83%E4%B8%A4%E4%B8%AA%E6%96%87%E4%BB%B6%EF%BC%8C%E5%9C%A8%20Bash%20Shell%20%E8%84%9A%E6%9C%AC%E4%B8%AD%E6%89%93%E5%8D%B0%E5%8F%A6%E4%B8%80%E4%B8%AA%E6%96%87%E4%BB%B6%E4%B8%AD%E5%80%BC%E7%9A%84%E5%B7%AE%E5%BC%82.png)
需要有关 shell 脚本的帮助,我有 2 个大约 1.2 GB 数据的大文件,带有键和值,我需要根据键比较两个文件,并存储第三个文件中的值与文件 1 中唯一的值的差异,
文件1:
test1 marco;polo;angus
test2 mike;zen;liza
test3 tom;harry;alan
test4 bob;june;janet
文件2:
test1 polo;angus
test2 mike
test4 bob;janet
我想比较 file1 和 file2 的前两列(搜索前两列中 file2 的全部内容),如果它们匹配,则打印值的差异。然后搜索文件1的第二行,依此类推。文件 1 中唯一的密钥也应该被打印。
预期输出:
test1 marco
test2 zen;liza
test3 tom;harry;alan
test4 june
我的文件很大,包含大约 100,000 行,所以我想让执行速度更快。这是在 shell 脚本中运行,使用#!/usr/bin/env bash.
例如:
1332239_44557576_CONTI Lased & Micro kjd $353.50_30062020_lsdf3_no-rule 343323H;343434311H;454656556H;343343432H
这是简单的文本文件,其作为键(1332239_44557576_CONTI Lased & Micro kjd $353.50_30062020_lsdf3_no-rule
),这些作为值:(343323H;343434311H;454656556H;343343432H
)
文件 2 始终是文件 1 的子集,只需查找文件 2 中不存在的值(针对键)以及文件 1 中唯一的值。
答案1
使用 perl 脚本:
假设您正在搜索文件2基于文件1反之则不然。如果您还想根据 file2 搜索 file1 那么您必须添加另一个 for 循环对于 file2 字典(hash) 。
数据文件:
$ cat file1.txt
test1 marco;polo;angus
test2 mike;zen;liza
test3 tom;harry;alan
test4 bob;june;janet
$ cat file2.txt
test1 polo;angus
test2 mike
test4 bob;janet
脚本 :
#!/usr/bin/perl
use warnings;
use strict;
my $file1=$ARGV[0];
my $file2=$ARGV[1];
my %dict1; #Stores file1 unique key and value pairs in this dictionary ( HASH in perl )
my %dict2; #Stores file2 unique key and value pairs in this dictionary ( HASH in perl )
my %output; #This is output dictionary after processing all the data to print it out
open(F1,'<',$file1) or die "File not found $file1";
open(F2,'<',$file2) or die "File not found $file2";
#Store both file's contents in %dict1 and %dict2 respectively
while(<F1>)
{
my ($key,$value) = split(/\s+/,$_);
$dict1{$key} = $value;
}
while(<F2>)
{
my ($key,$value) = split(/\s+/,$_);
$dict2{$key} = $value;
}
#Get the unique(difference) value from file2 based in the values in file1
foreach my $k ( keys %dict1 )
{
if ( defined $dict2{$k} )
{
my @dict1values=split(";",$dict1{$k});
my @dict2values=split(";",$dict2{$k});
foreach (@dict1values)
{
if ( $dict2{$k} !~ /[;]*?$_[;]*?/) {
$output{$k} .=$_.";";
}
}
} else {
$output{$k}=$dict1{$k};
}
}
foreach my $ke (sort(keys(%output)))
{
print "$ke $output{$ke}\n" if ( defined($output{$ke}) );
}
输出 :
$ ./testing.pl file1.txt file2.txt
test1 marco;
test2 zen;liza;
test3 tom;harry;alan
test4 june;
答案2
这是一个awk版本应该非常快。
适用于遵循请求的字段模式 [string:key][space|";"][string][space|";"] 等的任何内容。
$ cat file1;echo "";cat file2
test1 marco;polo;angus
test2 mike;zen;liza
test3 tom;harry;alan
test4 bob;june;janet
test1 polo;angus
test2 mike
test4 bob;janet
$ awk -F '[ ;]' '
NR==FNR{ for(i=2;i<=NF;i++){ k[$1,$i]++ } }
NR!=FNR{ for(i=2;i<=NF;i++){ k[$1,$i]++ } }
END{ for(i in k){
if(k[i]==1){
split(i,arr_i,SUBSEP);
k_e[arr_i[1]]=k_e[arr_i[1]]""arr_i[2]";"
}
}
for(i in k_e){
print i" "k_e[i]
}
}' file1 file2 | sort | sed 's/.$//'
test1 marco
test2 liza;zen
test3 harry;alan;tom
test4 june