将两个文件与第一列进行比较,并在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。

(你需要支持一个壳工艺替代像ksh93,zsh或bash)。


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.