select共享某些列(但不是全部)的行

我想修改一个文件,有7列。 input文件的例子是:

 1.txt 1 10 11 AL X3 -1.1 1 10 11 AL X1 1.1 1 13 21 AT X3 -2.1 3 11 12 AT X2 -3.1 3 11 12 KT X2 7.1 4 11 12 AT X7 -8.1 4 11 12 CT X7 -8.1 4 11 12 CT X7 11.1 

我想提取这些行共享前5列,但不同的最后两个也是其他不共享前5列。 然后,我想保留最后一列的最低值的行。

预期产出是:

  1 10 11 AL X3 -1.1 1 13 21 AT X3 -2.1 3 11 12 AT X2 -3.1 3 11 12 KT X2 7.1 4 11 12 AT X7 -8.1 4 11 12 CT X7 -8.1 

1st line是在这里,因为它与1.txt文件中的1.txt共享前5列。 在最后一列( -1.1 < 1.1 ,最后一行,我们保留-8.1因为它小于11.1 ),所以我们只保留它,我们保留其他行没有相同的前5字段。 我所尝试的是在awk保留前5列作为index ,但它只打印唯一的,而不是其余的。 而且它不会select最后一列中具有最低编号的行。 代码:

 awk -F"\t" '!seen[$1,$2,$3,$4,$5]++' 1.txt 

其输出:

 1 10 11 AL X3 -1.1 1 10 11 AL X1 1.1 1 13 21 AT X3 -2.1 3 11 12 AT X2 -3.1 3 11 12 KT X2 7.1 4 11 12 AT X7 -8.1 4 11 12 CT X7 -8.1 4 11 12 CT X7 11.1 

我不能select仅共享前5列的行,这些列的最后一列的值最低。 感谢您的帮助!

 awk ' {key = $1 FS $2 FS $3 FS $4 FS $5} !(key in min) || $NF < min[key] {min[key] = $NF; line[key] = $0} END {for (key in line) print line[key]} ' file 
  1 10 11 AL X3 -1.1 1 13 21 AT X3 -2.1 4 11 12 CT X7 -8.1 4 11 12 AT X7 -8.1 3 11 12 KT X2 7.1 3 11 12 AT X2 -3.1 

注意输出的顺序是不确定的。 你总是可以通过管道输出来sort ,或者使用GNU awk来控制数组遍历 。


我刚刚意识到line数组是完全不必要的,但会消耗大量的内存: min数组包含前5个字段作为键和第6个字段作为值

 awk ' {key = $1 FS $2 FS $3 FS $4 FS $5} !(key in min) || $NF < min[key] {min[key] = $NF} END {for (key in line) print key, min[key]} ' file 

由于交换可能需要很长时间。

awk来拯救! (在sort的帮助下)

 $ sort -k1,5 -k7n file | awk '!a[$1,$2,$3,$4,$5]++' 1 10 11 AL X3 -1.1 1 13 21 AT X3 -2.1 3 11 12 AT X2 -3.1 3 11 12 KT X2 7.1 4 11 12 AT X7 -8.1 4 11 12 CT X7 -8.1 

使用共享密钥(字段1到5)对记录进行分组,并按第七个字段以数字方式升序排列它们(因此第一个字段的最小值); 用awk来读取给定键的第一个记录(着名的awk成语,你在脚本中也使用过)。

这里是另一种没有awk方法

 $ sort -k1,5 -k7n file | rev | uniq -f2 | rev