Linux Bash:按数字列联接

Linux Bash:按数字列联接,linux,bash,shell,unix,join,Linux,Bash,Shell,Unix,Join,如果我想在我的Ubuntu上使用join,我需要首先按字典顺序对两个文件进行排序(根据join--help),然后才将它们合并: tail -n +2 meta/201508_1 | sort -k 1b,1 > meta.txt tail -n +2 keywords/copy | sort -k 1b,1 > keywords.txt join meta.txt keywords.txt -1 1 -2 1 -t $'\t' (我还使用tail从这两个文件中删除标题) 但我不

如果我想在我的Ubuntu上使用
join
,我需要首先按字典顺序对两个文件进行排序(根据
join--help
),然后才将它们合并:

tail -n +2 meta/201508_1 | sort -k 1b,1 > meta.txt
tail -n +2 keywords/copy | sort -k 1b,1 > keywords.txt
join meta.txt keywords.txt -1 1 -2 1 -t $'\t' 
(我还使用
tail
从这两个文件中删除标题)

但我不想按字典顺序对文件进行排序,而是想按数字顺序对它们进行排序:两个文件中的第一列都是一个ID

tail -n +2 meta/201508_1 | sort -k1 -n > meta.txt
tail -n +2 keywords/copy.txt | sort -k1 -n > keywords.txt
然后加入。但是对于
join
来说,这些文件看起来未排序:

join: meta.txt:10: is not sorted: 1023  301000  en
join: keywords.txt:2: is not sorted: 10 keyword1
如果我将
--nocheck order
添加到
join
,它就不能正确地连接,只输出一行

如何在bash中将两个文件的数字ID连接起来

示例(列以选项卡分隔):

文件1

id  volume lang
1   10  en
2   20  en
5   30  en
6   40  en
10  50  en
文件2

id  keyword
4   kw1
2   kw2
10  kw3
1   kw4
3   kw5
期望输出

1   kw4 10  en
2   kw2 20  en
10  kw3 50  en

您可以放弃
join
而改用
awk

awk -F'\t' 'FNR==1{next} NR==FNR{a[$1]=$2; next} $1 in a{print $1, a[$1], $2, $3}' file2 file1 | column -t
1   kw4  10  en
2   kw2  20  en
10  kw3  50  en
它可能已经按照您想要的顺序(根据file1中的ID列)。但是,如果需要特定的排序,可以执行以下操作:

awk -F'\t' 'FNR==1{next} NR==FNR{a[$1]=$2; next} $1 in a{
    print $1, a[$1], $2, $3}' file2 file1 | sort -nk1 | column -t

请注意,
column-t
用于生成表格格式的输出。

这两种方法都可以。第一个(
sort-b
is)


在任何情况下,您都需要按字典顺序对它们进行排序以加入它们。最后,您仍然可以对结果进行数字排序。

提供示例输入数据和预期输出。我添加了两个示例输入和预期输出如何按字典顺序对输入文件进行排序,然后像第一个示例一样将它们合并在一起,但是,然后将输出管道化到
sort-n
以获得键的数字顺序?它是否适用于大型文件?也就是说,它会导致一个大的交叉积和过滤器,还是会更智能,并利用正在排序的文件?不,我不是说缓存。它是否像
join
那样同时遍历两个文件,或者它首先在两个文件的行之间创建一个大的叉积,然后对其进行过滤?不,它不会创建任何叉积。它首先遍历
file2
,并将
$1->$2
的映射存储在关联数组中。一旦到达文件2的末尾,它将通过
file1
并使用存储的关联数组数据。我建议在较大的数据集上尝试。我没有尝试,我的文件太大,无法保存在内存中。我的
file2
只有两列。如果是5GB,它将占用多少内存?
join <(sed 1d file1 | sort -b) <(sed 1d file2 | sort -b) | sort -n
join <(sed 1d file1 | sort -k 1b,1) <(sed 1d file2 | sort -k 1b,1) | sort -n