连接列但打印两个文件中的所有行

时间:2014-03-18 18:52:28

标签: bash unix command-line

想象一下我有file1:

2 luke
3 matthew
4 mark
7 john

我有

1 chicken
2 beef
5 lamb
6 fish

我想要以下内容:

1 [tab]chicken
2 luke[tab]beef
3 matthew[tab]
4 mark[tab]
5 lamb[tab]
6 fish[tab]
7 [tab]john
喜欢"加入"但我也想要其他专栏。我知道我可以使用3" comm" s并使用sort来调整它但是有一个命令可以做到吗?

5 个答案:

答案 0 :(得分:3)

您只需要使用join的几个选项:

join -a1 -a2 -o 0,1.2,2.2 -e $'\t' tmp1.txt tmp2.txt

-a1-a2告诉join输出文件1和文件2中无法配对的行(因此包含两个文件中的所有行)。 -o在输出中指定三列:连接字段(0),第一个文件中的第二列和第二个文件中的第二列。 -e指定用于填充空字段的字符串(未找到字段)。 $'\t'bash扩展名;传递制表符的更兼容方式是-e $(printf '\t')

答案 1 :(得分:1)

您也可以使用AWK:

awk 'FNR==NR{a[$1]=$2; i++; next}{ b[$1]=$2; i++} END { OFS="\t"; for (n=1;n<i;++n) print n, a[n], b[n] }' file1 file2

这会经过file1(第一个{block})和file2(第二个{block},构建由第一列中的数字索引的数组。然后在最后打印输出每个数组中的所有值。

答案 2 :(得分:0)

这会使用制表符填充空字段,但字段仍以空格分隔。

join  -a1 -a2 -o 0,1.2,2.2 -e $'\t' file1 file2
1    chicken
2 luke beef
3 matthew   
4 mark  
5    lamb
6    fish
7 john  

要查看空白字符,请将输出通过管道传输到| od -c

要准确获得所需的输出,请使用awk:

awk '
    {
        ids[$1]
        if (NR==FNR) 
            f1[$1]=$2
        else 
            f2[$1]=$2
    } 
    END {
        n = asorti(ids, sorted_ids)
        for (i=1; i<=n; i++)
            printf "%d %s\t%s\n", sorted_ids[i], f1[sorted_ids[i]], f2[sorted_ids[i]]
    }
' file1 file2
1   chicken
2 luke  beef
3 matthew   
4 mark  
5   lamb
6   fish
7 john  

答案 3 :(得分:0)

这个awk应该可以工作:

awk 'FNR==NR{a[$1]=$2;next} $1 in a{print $1, $2, a[$1];delete a[$1];next} {print $1, $2, ""}
     END {for (i in a) print i, a[i]}' OFS='\t' f2 f1|sort -nk1
1   chicken
2   luke    beef
3   matthew
4   mark
5   lamb
6   fish
7   john

答案 4 :(得分:0)

以下是awk的另一种方式。只需将[tab]替换为\t即可。

awk '
NR==FNR { a[$1] = $2 "[tab]"; next }
($1 in a) { a[$1] = a[$1] $2; next }
{ a[$1] = "[tab]" $2 }
END {
    n = asorti(a, s);
    for (x = 1; x <= n; x++)
        print s[x], a[s[x]]}
' file1 file2
1 [tab]chicken
2 luke[tab]beef
3 matthew[tab]
4 mark[tab]
5 [tab]lamb
6 [tab]fish
7 john[tab]