我有 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$2
foobar
{print "2019",$0,"0"}
: 打印和2019
中的当前行。file2
0
答案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
这并不像awk
RoVo 和 Tendon 的纯粹解决方案那么短,但我认为这是一个有趣的解决方案,因为join
可以用来“过滤掉”您想要的行。