将两个文件与第一列进行比较,并在Shell脚本中从第二个文件中删除重复的行


9

我将用一个例子来问我的问题。我有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的第3个文件中。

Answers:


10

您可以awk为此使用:

awk 'FNR==NR{a[$1];next};!($1 in a)' file1 file2 > file3

说明:

  • FNR == NR:当记录数等于文件中的记录数时,此测试为true。这仅对第一个文件适用,对于第二个文件NR将等于file1 +的行数FNR

  • a[$1]:创建file1第一个字段的数组元素索引。

  • next:跳到下一条记录,因此不再对file1进行任何处理。

  • !($1 in a):查看数组(即file1)中是否存在第一个字段($ 1),并打印整行(至file3)。

基于#awk Wiki中的示例之一。


完美答案!!!
mtk

8
export LC_ALL=C
comm -13 <(sort f1) <(sort  f2)

将仅报告中的行f2

export LC_ALL=C
join -v2 <(sort f1) <(sort f2)

将报告f2其第一个字段未找到的行作为的任何行中的第一个字段f1

(你需要支持一个壳工艺替代像ksh93zshbash)。


2

只是为了好玩,这是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个循环组成。第一个循环从中读取所有行file1并创建一个哈希,%names在哈希中添加我们标识的每一列。

$names{11AA} = 1;

然后第二个while循环在第二个文件上运行file2,并使用正则表达式标识每一行的列1:

^(\S+).*

上面从行的开头说,匹配所有不是空格的内容,并将其保存在临时变量中$1。通过将paren包裹起来可以节省时间。的.*说,以匹配所有其他线上。

该线的下位说来查找列1位,我们只是保存$1%names哈希:

$names{$1}

如果它在那里,那么我们不想打印它。如果不存在,请打印出来。


2

方法1#重击

#!/usr/bin/env bash
file1=$1
file2=$2

[[ $# -ne 2 ]]  && { echo -e "\n\tUsage: \t$0 file1 file2\n"; exit 1; }

while read line
do

        if ! grep -q "${line%% .*}" $file1; then
                echo "${line}"
        fi

done < $file2

方法2#仅Grep

grep -v "$(< file1)" file2

grep正在工作,但不能保证


1

让我们得到它

档案#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)

这仅在整行相同的情况下有效,但发问者仅在第一列上明确要求进行比较。
阿达芬2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.