Bash:自定义排序/为每个ID组,将某一行移到组

时间:2018-04-11 02:06:24

标签: bash sorting unix match move

我有一个8列文件,前两列是ID。第一列中的ID最多重复12次12次。我需要按第一列ID进行迭代,当我找到col1 = col2的行时,我需要将此行移动到该ID组的顶部。一个复杂因素是匹配部分仅是列1 ID和列2 ID中的一个。该文件已经排序。以下是输入的示例:

aac(3)-IIa_1_X51534     lcl|JQ364967.1_cds_AFI72859.1_82        99.768 
aac(3)-IIa_1_X51534     lcl|X51534.1_cds_CAA35913.1_1   100.000    
aac(3)-IIa_1_X51534     lcl|EU022315.1_cds_ABS70978.1_1 99.535 
aac(6')-33_1_GQ337064   lcl|GQ337064.1_cds_ACT99625.1_2 100.000 
aac(6')-33_1_GQ337064   lcl|JN596280.1_cds_AEZ05106.1_2 100.000 
aac(6')-aph(2'')_1_M13771       lcl|CP000029.1_cds_AAW54933.1_1550   100.000
aac(6')-aph(2'')_1_M13771       lcl|M13771.1_cds_AAA26865.1_1   100.000 
aac(6')-aph(2'')_1_M13771       lcl|FN433596.1_cds_CBI49941.1_2062      99.931

所需的输出是:

aac(3)-IIa_1_X51534     lcl|X51534.1_cds_CAA35913.1_1   100.000       
aac(3)-IIa_1_X51534     lcl|JQ364967.1_cds_AFI72859.1_82        99.768 
aac(3)-IIa_1_X51534     lcl|EU022315.1_cds_ABS70978.1_1 99.535 
aac(6')-33_1_GQ337064   lcl|GQ337064.1_cds_ACT99625.1_2 100.000 
aac(6')-33_1_GQ337064   lcl|JN596280.1_cds_AEZ05106.1_2 100.000 
aac(6')-aph(2'')_1_M13771       lcl|M13771.1_cds_AAA26865.1_1   100.000 
aac(6')-aph(2'')_1_M13771       lcl|CP000029.1_cds_AAW54933.1_1550   100.000
aac(6')-aph(2'')_1_M13771       lcl|FN433596.1_cds_CBI49941.1_2062      99.931

我将匹配线(在第一个中,它是X51534)移动到组的顶部。 (但它并不总是组中的第二行。)我可以使用Perl,或者在Bash中使用很长的路径(使用多个循环)。但是,我认为应该有一个简洁的解决方案(也许使用awk)?我已经使用关联数组尝试了许多awk解决方案,但由于某些原因我无法解决这个问题。我养成了使程序过于复杂的习惯(正在努力)。有什么提示吗?

1 个答案:

答案 0 :(得分:2)

awk救援!

$ awk '{n=split($1,a,"_"); print ($2~a[n]) "\t" $0}' | 
  sort -k2,2 -k1,1r -s | cut -f2-