根据同一字段中的排序值合并两个排序文件

根据同一字段中的排序值合并两个排序文件

我想合并两个排序文件中的行,不一定具有相同的长度,但具有相同的数据字段和相同的标题,从基于特定列的顺序的维护标题之后开始。例如,文件1为:

header 1
header 2
header 3

cat    4    aa
dog    5    ab
ostrich    10    cd
fish    13    cc

文件2是:

header 1
header 2
header 3

lemur    3    dd
alligator    4    ca
lemming    16    ad

我想 1) 保留相同的标题,但 2) 根据第 2 列对以下行进行排序。我想要的输出是:

header 1
header 2
header 3

lemur    3    dd
cat    4    aa
alligator     4    ca
dog    5    ab
ostrich    10    cd
fish    13    cc
lemming     16    ad

我已经查看过,但无法使用awkor找到针对这种情况的解决方案join

答案1

awkjoin是错误的工具。

sed '/^$/q' file1; sort -snmk2,2 <(sed '1,/^$/d' file1) <(sed '1,/^$/d' file2)

答案2

使用现代(版本> 4.0)的 GNU awk,你可以这样做

awk '
  FNR>4 {a[$0]=$2; next}; 
  NR==FNR; 
  END {
    PROCINFO["sorted_in"] = "@val_num_asc"; 
    for (i in a) print i;
  }
' file1 file2

解释:

  • FNR>4 {a[$0]=$2; next};创建非标题行的排序字段的数组
  • NR==FNR;仅对第一个文件评估 TRUE,并且仅对 达到FNR>4,导致为第一个文件打印标题行
  • PROCINFO["sorted_in"] = "@val_num_asc"按值对数组进行排序(即存储字段 $2)
  • for (i in a) print i打印指数排序数组的(存储的非标题行)

测试

$ awk 'FNR>4 {a[$0]=$2; next}; NR==FNR; END {PROCINFO["sorted_in"] = "@val_num_asc"; for (i in a) print i;}' file1 file2
header 1
header 2
header 3

lemur    3    dd
cat    4    aa
alligator    4    ca
dog    5    ab
ostrich    10    cd
fish    13    cc
lemming    16    ad

答案3

使用具有进程替换的 shell ( ksh93, bash, ...) (参见结尾以了解无进程替换的替代方案):

cat <( head -n 3 file1 ) \
    <( sort -k2,2n <( tail -n +4 file1 | tr -s ' ' '\t' ) \
                   <( tail -n +4 file2 | tr -s ' ' '\t' ) | uniq )

这将导致:

header 1
header 2
header 3

lemur   3       dd
alligator       4       ca
cat     4       aa
dog     5       ab
ostrich 10      cd
fish    13      cc
lemming 16      ad

该命令将标题行file1与排序操作的结果连接起来。排序是在某些输入的第二个字段上以数字方式完成的,并且任何重复的行(鳄鱼、狐猴和旅鼠)都会从uniq结果中删除。

file1sort 的输入将是和的无标题内容file2,传递tr以用单个制表符替换连续空格(示例数据中的列之间的空格数量不均匀)。

结果以制表符分隔。


使用相同工具的等效方法:

cat <( head -n 3 file1 ) \
    <( sort -k2,2n <( cat <( tail -n +4 file1 ) \
                          <( tail -n +4 file2 ) | tr -s ' ' '\t' ) | uniq )

没有cats 和进程替换:

{ head -n 3 file1;
    { tail -n +4 file1; tail -n +4 file2; } | tr -s ' ' '\t' | sort -k2,2n | uniq; }

相关内容