我会用一个例子来问我的问题。我有2个文件:
文件#1:
118D FC300_R5_TP FX.B 32775 2112 6 2038 6 2112 0
118E FC300_R5_TP FX.B 32775 2136 7 2065 6 2136 0
118F FC300_R5_TP FX.B 32775 2124 6 2064 6 2124 0
1190 FC300_R5_TP FX.B 819210 814632 99 814609 99 814632 0
1191 FC300_R5_TP FX.B 819210 104100 13 103714 13 104100 0
1192 FC300_R5_TP FX.B 1638420 1609476 98 1609402 98 1609476 0
1196 FC300_R5_TP FX.B 1638420 1638432 100 1638379 100 1638432 0
119A FC300_R5_TP FX.B 3276840 3271776 100 3271698 100 3271776 0
119E FC300_R5_TP FX.B 3276840 3264120 100 3264034 100 3264120 0
11A2 FC300_R5_TP FX.B 3276840 2328648 71 2328546 71 2328648 0
11A6 FC300_R5_TP FX.B 3276840 2328444 71 2328355 71 2328444 0
11AA FC300_R5_TP FX.B 3276840 2328528 71 2328403 71 2328528 0
11AE FC300_R5_TP FX.B 3276840 2328648 71 2328468 71 2328648 0
11B2 FC300_R5_TP FX.B 3276840 2130000 65 2129766 65 2130000 0
173A FC300_R5_TP FX.B 6553680 6478572 99 6477747 99 6478572 0
文件#2:
11AA FC300_R5_TP FX.B 3276840 2328528 71 2328403 71 2328528 0
11AE FC300_R5_TP FX.B 3276840 2328648 71 2328468 71 2328648 0
11B2 FC300_R5_TP FX.B 3276840 2130000 65 2129766 65 2130000 0
173A FC300_R5_TP FX.B 6553680 6478572 99 6477747 99 6478572 0
0BDB FC600_R5_TP FX.B 33554640 6044364 18 6033105 18 6044364 0
0BDC FC600_R5_TP FX.B 33554640 6613536 20 6481974 19 6613536 0
0BDD FC600_R5_TP FX.B 33554640 4435848 13 4057170 12 4435848 0
0BDE FC600_R5_TP FX.B 33554640 6620868 20 6249518 19 6620868 0
所需输出
文件#3:
0BDB FC600_R5_TP FX.B 33554640 6044364 18 6033105 18 6044364 0
0BDC FC600_R5_TP FX.B 33554640 6613536 20 6481974 19 6613536 0
0BDD FC600_R5_TP FX.B 33554640 4435848 13 4057170 12 4435848 0
0BDE FC600_R5_TP FX.B 33554640 6620868 20 6249518 19 6620868 0
我想使用文件 1 和文件 2 的第一列进行比较,并从文件 2 中删除它们在文件 1 中匹配的整行或行。我还想将结果保存到第三个文件,文件 #3。
答案1
您可以awk
为此使用:
awk 'FNR==NR{a[$1];next};!($1 in a)' file1 file2 > file3
解释:
FNR == NR
:当记录数等于文件中的记录数时,此测试为真。这仅适用于第一个文件,因为第二个文件NR
将等于 file1 + 的行数FNR
。a[$1]
:创建file1第一个字段的数组元素索引。next
:跳到下一条记录,因此不再对 file1 进行任何处理。!($1 in a)
:查看第一个字段($1)是否存在于数组中,即文件1中,并打印整行(到文件3)。
基于以下示例之一#awk 维基。
答案2
export LC_ALL=C
comm -13 <(sort f1) <(sort f2)
将报告仅在f2
.
export LC_ALL=C
join -v2 <(sort f1) <(sort f2)
会将未找到第一个字段的行报告f2
为 的任何行中的第一个字段f1
。
(您需要一个支持进程替换的 shell,例如ksh93
,zsh
或bash
)。
答案3
只是为了好玩,这里有一个 Perl 解决方案:
#!/usr/bin/perl
# create names lookup table from first file
my %names;
while (<>) {
(my $col1)= split / /, $_;
$names{$col1} = 1;
last if eof;
}
# scan second file
while (<>) {
print if /^(\S+).*/ && not $names{$1};
}
例子
$ ./showdiffs.pl file1 file2
0BDB FC600_R5_TP FX.B 33554640 6044364 18 6033105 18 6044364 0
0BDC FC600_R5_TP FX.B 33554640 6613536 20 6481974 19 6613536 0
0BDD FC600_R5_TP FX.B 33554640 4435848 13 4057170 12 4435848 0
0BDE FC600_R5_TP FX.B 33554640 6620868 20 6249518 19 6620868 0
细节
上面的 Perl 解决方案由 2 个循环组成。第一个循环读取 from 中的所有行file1
并创建一个散列,%names
其中添加我们识别的每一列。
$names{11AA} = 1;
然后,第二个while
循环对第二个文件 运行,file2
并使用正则表达式标识每行的第 1 列:
^(\S+).*
上面说从行的开头开始,匹配所有不是空格的内容,并将其保存在临时变量中$1
。通过用括号括起来可以保存它。上面.*
说要匹配线上的所有其他内容。
该行的下一位表示查找我们刚刚保存在哈希$1
中的列 1 位%names
:
$names{$1}
如果它存在,那么我们不想打印它。如果不存在,则打印它。
答案4
让我们把它当作
文件#1:file1.txt
文件#2:file2.txt
然后在终端上运行以下命令
fgrep -vf test1.txt test2.txt > output.txt
output.txt 将包含所需的结果。
解释:
fgrep : print lines matching a pattern (from manual page)
-v : get only non-matching rows
-f : obtain PATTERN from FILE (from manual page)