如何在awk中打​​印/存储数组中的重复值

时间:2017-04-20 11:47:13

标签: arrays shell awk

我有两个文件。我想在file2的基础上打印file1的数据。

File1中:

a 1 
b 2 
c 3 
d 4 
e 1 
f 5 
g 1

文件2:

1 100
2 200
3 400
4 600
5 700

使用以下命令:

 awk 'NR==FNR{a[$2]=$1;next}$1 in a{print a[$1] " " $2}' file1 file2

我得到了以下输出:

g 100
b 200
c 400
d 600
f 700

但我不希望在数组中覆盖重复值。 期望的输出:

a 100
e 100
g 100
b 200
c 400
d 600
f 700

是否可以在awk脚本中将重复键存储在数组中,如C ++中的multimap。或者还有另一种方法吗?请帮帮我。

4 个答案:

答案 0 :(得分:4)

如果(且仅当)第二个文件的第一个字段(单个数字的数字)是唯一的,您可以转动逻辑并使用该字段作为数组的键:

$ awk 'FNR==NR { a[$1] = $2; next } $2 in a {print $1, a[$2]} ' file2 file1
a 100
b 200
c 400
d 600
e 100
f 700
g 100

现在输出顺序是file1的顺序,所以不是你想要的,但到sort -nk2的管道将解决这个问题。

如果第一个文件有第二个字段不在第二个文件中的行(例如h 9),那么该怎么做的边界情况。 $2 in a条件将完全跳过这些条件。如果没有这些条件,它们将被打印,并带有一个空的第二个字段(输出中只有h[space])。

答案 1 :(得分:3)

使用GNU awk实现真正的多维数组:

$ awk 'NR==FNR{a[$2][$1]=$1;next} $1 in a{for (i in a[$1]) print a[$1][i], $2}' file1 file2
a 100
e 100
g 100
b 200
c 400
d 600
f 700

其他问题:

$ awk 'NR==FNR{a[$2]=a[$2] FS $1;next} $1 in a{split(a[$1],b); for (i in b) print b[i], $2}' file1 file2
a 100
e 100
g 100
b 200
c 400
d 600
f 700

由于in运算符,每个键的输出顺序将是随机的,如果问题让我们知道您需要什么顺序。

答案 2 :(得分:2)

您可以使用join命令 在join命令之前,您必须使用sort命令对文件进行排序。

$ sort -k 2 file1 > file1_sort  
$ sort -k 1 file2 > file2_sort  
$ join -1 2 -2 1 file1_sort file2_sort -o 1.1,2.2 > new_file  
$ rm file1_sort  
$ rm file2_sort  
$ cat new_file
a 100
e 100
g 100
b 200
c 400
d 600
f 700


使用Process Substitution

$ join -1 2 -2 1 <(sort -k2 file1) <(sort file2) -o 1.1,2.2
a 100
e 100
g 100
b 200
c 400
d 600
f 700

答案 3 :(得分:1)

在第一个回复后回复标题而不是OP本身,第二个版本为OP(原始回复完全修改)

awk 'FNR==NR{R[$1]=$2;next}{$2=R[$2]}7' File2 File1