比较两个文件,忽略匹配的内容,将文件2中不匹配的内容以特定格式追加到文件1中

比较两个文件,忽略匹配的内容,将文件2中不匹配的内容以特定格式追加到文件1中

我有 2 个文件需要将 file1 2ns 和 3 ed 列与 file2 第一列和第二列进行比较,如果匹配则保留它,如果不匹配则通过添加 2019 作为第一列和 0 作为最后一列来附加 file1 中的数据。这可能吗?

文件1

2019  ABCD 1 10
2019  DEF  2 11
2019  GHI  1 20
2019  jkl  2 25

文件2

ABCD 1
jkl  1
mnop  2
qrst  1

预期结果

2019  ABCD 1 10
2019  DEF  2 11
2019  GHI  1 20
2019  jkl  2 25
2019  jkl  1  0
2019  mnop  2  0
2019  qrst  1  0

答案1

尝试这个:

awk '
     FNR==NR {seen[$2,$3]=1; print $0 }
     FNR!=NR && !seen[$1,$2] { print 2019,$0,0 }
' file1 file2

解释:

  • FNR==NR { ... }仅对第一个文件运行括号中的命令。
  • seen[$2,$3]=1,将seen键 $2,$3 的数组设置为 1。
  • print $0打印整行。
  • FNR!=NR && !seen[$1,$2] { ... }仅当不是第一个文件并且字段 $1、$2 不是seen数组中的键时才运行括号中的命令。
  • print 2019,$0,0打印由新列 2019 和 0 包围的行。

添加| column -t对齐输出。

输出:

$ awk 'FNR==NR{seen[$2,$3]++; print $0} FNR!=NR && !seen[$1,$2]{print 2019,$0,0}' file1 file2 | column -t
2019  ABCD  1  10
2019  DEF   2  11
2019  GHI   1  20
2019  jkl   2  25
2019  jkl   1  0
2019  mnop  2  0
2019  qrst  1  0

答案2

这应该有效:

$ awk 'NR==FNR{a[$2$3]++; print; next}!($1$2 in a){print "2019",$0,"0"}' file1 file2 
2019  ABCD 1 10
2019  DEF  2 11
2019  GHI  1 20
2019  jkl  2 25
2019 jkl  1 0
2019 mnop  2 0
2019 qrst  1 0

解释

  • NR==FNR:NR为当前行号,FNR为当前文件的行号。仅当读取第一个文件时,两者才会相同。
  • {a[$2$3]++; print; next}:读取第一个文件 ( file1) 时,使用第二个和第三个字段作为关联数组的键a。这只是用来跟踪我们已经看过的内容。然后,打印此行并继续下一行。这next可确保脚本的其余部分仅针对第二个文件运行(当NR与 不同时)FNR
  • !($1$2 in a):如果该行的第一个和第二个字段不用作数组中的键a(这意味着第一个和第二个字段连接在一起,因此如果第一个字段是,foo第二个字段将是)。 bar$1$2foobar
  • {print "2019",$0,"0"}: 打印和2019中的当前行。file20

答案3

这是一种非常不同的方法:

mkns() {
    # make keys from parameters $2 and $3 for joining, then sort the keys
    sort -k 1b,1 <(awk "{print \$$2\$$3, \$0}" $1)
}

然后运行

join -j 1 -v 2 <(mkns file1 2 3) <(mkns file2 1 2) | awk '{print 2019, $2, $3, 0}' | cat file1 - | column -t

这并不像awkRoVo 和 Tendon 的纯粹解决方案那么短,但我认为这是一个有趣的解决方案,因为join可以用来“过滤掉”您想要的行。

相关内容