如何比较两个文件之间的值?
how to compare values between two files?
我有两个文件,两列由 space
分隔
cat file1.txt
281475225437349 33,32,21,17,20,22,18,30,19,16,23,31
281475550885480 35,32,33,21,39,40,57,36,41,17,20,38,34,37,16,99
cat file2.txt
281475550885480 16,17,20,21,32,33,34,35,36,37,38,39,40,41
281475225437349 16,17,18,19,20,21,22,23,24,25,30,31,32,33
我想比较 file1 column2 和 file2 column2 中 column1 中相同值的值。
并仅打印那些确实存在于 file1 column2 中但不存在于 file2 column2 中的值,反之亦然以及 column1
中的相应值
想要o/p
它不应该为 281475225437349 打印任何内容,因为 file1 column2 中的所有值都存在于 file2 column 2 for 281475225437349
它应该只打印 281475550885480 的值,它存在于 file1 column2 但不存在于 file2 column2 中。像 281475550885480
的值 57 和 99
因此 o/p 文件如下:
cat output.txt
281475550885480 57,99
我已经尝试使用 sdiff 对文件进行排序和比较,但它会产生差异并花费时间
sdiff file1.txt file2.txt
您必须在代码中使用两个循环。同样拆分','字符并设置两个数组,在
之后
foreach(var itemOne as arrayOne){
boolean isExist=false;
foreach(var itemTwo as arrayTwo)
if(itemOne==itemTwo) isExist=true;
if(isExist) console.log(itemOne+" is exist");
}
Perl 解决方案:从第二个文件创建散列的散列。键是大数字,内部键是逗号分隔列表中较小的数字。然后遍历第一个文件并检查记忆结构中没有提到的数字。
#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };
open my $f1, '<', 'file1' or die $!;
open my $f2, '<', 'file2' or die $!;
my %seen;
while (<$f2>) {
my ($key, $value_string) = split ' ';
my @values = split /,/, $value_string; #/
undef @{ $seen{$key} }{@values};
}
while (<$f1>) {
my ($key, $value_string) = split ' ';
my @values = split /,/, $value_string;
my %surplus;
undef @surplus{@values};
delete @surplus{ keys %{ $seen{$key} } };
say $key, ' ', join ',', keys %surplus
if keys %surplus;
}
顺便说一句,当你切换文件时,输出将是
281475225437349 24,25
因为文件 1 中不存在 24 和 25。
awk 很简单:
awk '(NR==FNR) { a[]=","","; next }
{ delete b } # clear array for new run
{ split(,f,",") } # split string of file1 in array f
{ for(i in f) if (! match(a[],"," f[i] ",")) b[f[i]] }
{ c=" "; for(i in b) {printf c i; c="," }; if (c==",") printf "\n" }' file2 file1
哪个returns:
281475550885480 57,99
想法是用额外的两个 存储第二列的字符串,以确保每个数字都在逗号之间。然后搜索逗号夹子字符串。
如果您必须进行实数检查并且您可能必须比较数字“5”和“005”并且它们应该相等,那么您应该执行以下操作:
awk '(NR==FNR) { a[]=; next }
{ delete b } # clear array
{ # split strings in number elements
split(,f,","); for(i in f) f1[f[i]+0];
split(a[],f,","); for(i in f) f2[f[i]+0]
}
{ for(i in f1) if (! (i in f2)) b[i] }
{ c=" "; for(i in b) {printf c i; c="," }; if (c==",") printf "\n" }' file2 file1
这可能对你有用 (GNU sed):
sed -r 's#^(\S+)\s(\S+)$#/^ /s/$/,\n,/#' file2 |
sed -rnf - -e ':a;s/(\b[0-9]+,)(.*\n.*)//;ta;s/(.*),\n.*//p' file1
解决方案可以分为两部分。
首先将 file2 转换为 sed 脚本,该脚本将每个键的值附加到 file1 中的相同键。添加了额外的 ,
以使匹配更容易,并将作为 file1 中的行是否具有要打印的值的指示符。
从 file2 生成的脚本通过管道传输到第二个 sed 调用中,另外一个下标使用替换和循环从 file1 中删除匹配值。
在匹配失败时,因为第二次 sed 调用使用 -n
开关来显式打印,最终匹配删除引入的 ,
和换行符后的不匹配值并打印要求的结果。
$ cat tst.awk
BEGIN { FS="[ ,]" }
NR==FNR {
for (i=2; i<=NF; i++) {
file2[,$i]
}
next
}
{
diff = ""
for (i=2; i<=NF; i++) {
if ( !((,$i) in file2) ) {
diff = (diff == "" ? "" : diff ",") $i
}
}
if (diff != "") {
print , diff
}
}
$ awk -f tst.awk file2 file1
281475550885480 57,99
另一个awk
$ awk -v c=, 'NR==FNR {a[]=; next}
{for(i=2;i<=NF;i++)
{if(c a[] c !~ c $i c) p=(p==""?" ":p c) $i}
if(p) print p; p=""}' file2 FS=' |,' file1
281475550885480 57,99
我有两个文件,两列由 space
分隔cat file1.txt
281475225437349 33,32,21,17,20,22,18,30,19,16,23,31
281475550885480 35,32,33,21,39,40,57,36,41,17,20,38,34,37,16,99
cat file2.txt
281475550885480 16,17,20,21,32,33,34,35,36,37,38,39,40,41
281475225437349 16,17,18,19,20,21,22,23,24,25,30,31,32,33
我想比较 file1 column2 和 file2 column2 中 column1 中相同值的值。 并仅打印那些确实存在于 file1 column2 中但不存在于 file2 column2 中的值,反之亦然以及 column1
中的相应值想要o/p
它不应该为 281475225437349 打印任何内容,因为 file1 column2 中的所有值都存在于 file2 column 2 for 281475225437349
它应该只打印 281475550885480 的值,它存在于 file1 column2 但不存在于 file2 column2 中。像 281475550885480
的值 57 和 99因此 o/p 文件如下:
cat output.txt
281475550885480 57,99
我已经尝试使用 sdiff 对文件进行排序和比较,但它会产生差异并花费时间
sdiff file1.txt file2.txt
您必须在代码中使用两个循环。同样拆分','字符并设置两个数组,在
之后foreach(var itemOne as arrayOne){
boolean isExist=false;
foreach(var itemTwo as arrayTwo)
if(itemOne==itemTwo) isExist=true;
if(isExist) console.log(itemOne+" is exist");
}
Perl 解决方案:从第二个文件创建散列的散列。键是大数字,内部键是逗号分隔列表中较小的数字。然后遍历第一个文件并检查记忆结构中没有提到的数字。
#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };
open my $f1, '<', 'file1' or die $!;
open my $f2, '<', 'file2' or die $!;
my %seen;
while (<$f2>) {
my ($key, $value_string) = split ' ';
my @values = split /,/, $value_string; #/
undef @{ $seen{$key} }{@values};
}
while (<$f1>) {
my ($key, $value_string) = split ' ';
my @values = split /,/, $value_string;
my %surplus;
undef @surplus{@values};
delete @surplus{ keys %{ $seen{$key} } };
say $key, ' ', join ',', keys %surplus
if keys %surplus;
}
顺便说一句,当你切换文件时,输出将是
281475225437349 24,25
因为文件 1 中不存在 24 和 25。
awk 很简单:
awk '(NR==FNR) { a[]=","","; next }
{ delete b } # clear array for new run
{ split(,f,",") } # split string of file1 in array f
{ for(i in f) if (! match(a[],"," f[i] ",")) b[f[i]] }
{ c=" "; for(i in b) {printf c i; c="," }; if (c==",") printf "\n" }' file2 file1
哪个returns:
281475550885480 57,99
想法是用额外的两个
如果您必须进行实数检查并且您可能必须比较数字“5”和“005”并且它们应该相等,那么您应该执行以下操作:
awk '(NR==FNR) { a[]=; next }
{ delete b } # clear array
{ # split strings in number elements
split(,f,","); for(i in f) f1[f[i]+0];
split(a[],f,","); for(i in f) f2[f[i]+0]
}
{ for(i in f1) if (! (i in f2)) b[i] }
{ c=" "; for(i in b) {printf c i; c="," }; if (c==",") printf "\n" }' file2 file1
这可能对你有用 (GNU sed):
sed -r 's#^(\S+)\s(\S+)$#/^ /s/$/,\n,/#' file2 |
sed -rnf - -e ':a;s/(\b[0-9]+,)(.*\n.*)//;ta;s/(.*),\n.*//p' file1
解决方案可以分为两部分。
首先将 file2 转换为 sed 脚本,该脚本将每个键的值附加到 file1 中的相同键。添加了额外的 ,
以使匹配更容易,并将作为 file1 中的行是否具有要打印的值的指示符。
从 file2 生成的脚本通过管道传输到第二个 sed 调用中,另外一个下标使用替换和循环从 file1 中删除匹配值。
在匹配失败时,因为第二次 sed 调用使用 -n
开关来显式打印,最终匹配删除引入的 ,
和换行符后的不匹配值并打印要求的结果。
$ cat tst.awk
BEGIN { FS="[ ,]" }
NR==FNR {
for (i=2; i<=NF; i++) {
file2[,$i]
}
next
}
{
diff = ""
for (i=2; i<=NF; i++) {
if ( !((,$i) in file2) ) {
diff = (diff == "" ? "" : diff ",") $i
}
}
if (diff != "") {
print , diff
}
}
$ awk -f tst.awk file2 file1
281475550885480 57,99
另一个awk
$ awk -v c=, 'NR==FNR {a[]=; next}
{for(i=2;i<=NF;i++)
{if(c a[] c !~ c $i c) p=(p==""?" ":p c) $i}
if(p) print p; p=""}' file2 FS=' |,' file1
281475550885480 57,99