Bash 在第一列中连接具有相同值的行

Bash 在第一列中连接具有相同值的行,bash,awk,Bash,Awk,我有一个以制表符分隔的文件,有三列(摘录): 我想用bash得到这个: AC147602.5_FG004 IPR000146 Fructose-1,6-bisphosphatase class 1/Sedoheputulose-1,7-bisphosphatase IPR023079 Sedoheptulose-1,7-bisphosphatase AC148152.3_FG001 IPR023079 Sedoheptulose-1,7-bisphosphatase IPR002110 An

我有一个以制表符分隔的文件,有三列(摘录):

我想用bash得到这个:

AC147602.5_FG004 IPR000146 Fructose-1,6-bisphosphatase class 1/Sedoheputulose-1,7-bisphosphatase IPR023079 Sedoheptulose-1,7-bisphosphatase
AC148152.3_FG001 IPR023079 Sedoheptulose-1,7-bisphosphatase IPR002110   Ankyrin repeat IPR026961    PGG domain

因此,如果第一列中的ID在几行中是相同的,那么它应该为每个ID生成一行,并将行的所有其他部分连接起来。在本例中,它将提供两行文件。

请尝试使用这一行:

 awk -F'\t' -v OFS='\t' '{x=$1;$1="";a[x]=a[x]$0}END{for(x in a)print x,a[x]}' file

无论出于何种原因,awk解决方案在cygwin中对我不起作用。所以我改用Perl。它围绕一个制表符连接,并按空格分隔行\n

cat FILENAME | perl -e 'foreach $Line (<STDIN>) { @Cols=($Line=~/^\s*(\d+)\s*(.*?)\s*$/); push(@{$Link{$Cols[0]}}, $Cols[1]); } foreach $List (values %Link) { print join("\t", @{$List})."\n"; }'
cat FILENAME | perl-e'foreach$Line(){@Cols=($Line=~/^\s*(\d+)\s*(.*?\s*/);push(@{$Link{$Cols[0]},$Cols[1]);}foreach$List(值%Link){print join(“\t”,“@{$List})。“\n”;}
将取决于文件大小(和awk限制)

如果太大,这将通过首先对文件进行排序并在内存中仅保留1个标签进行打印来减少awk需求

对整行进行修改后打印的经典版本

sort YourFile \
 | awk '
      last==$1 { sub( /^[^[:blank:]]*[[:blank:]]+/, ""); C = C " " $0; next}
      NR > 1 { print Last C; Last = $1; C = ""}
      END { print Last}
      '
另一个版本使用字段和预打印,但不太“可读”

对文件进行排序\
|awk'
最后=$1{printf(“%s%s”,(!NR?”\n:“),Last=$1)}

最后==1元{(i=2;i@oberlies,有时可以在问题中添加标签,这些标签涵盖了答案中使用的技术,但在问题中没有提及。这就是其中之一,尤其是当替代方案是创建新的元标签时。@亲密投票者:这个问题怎么可能太宽?答案是一行awk脚本。
sort YourFile \
 | awk '
      last==$1 { sub( /^[^[:blank:]]*[[:blank:]]+/, ""); C = C " " $0; next}
      NR > 1 { print Last C; Last = $1; C = ""}
      END { print Last}
      '
sort YourFile \
 | awk '
      last!=$1 {printf( "%s%s", (! NR ? "\n" : ""), Last=$1)}
      last==$1 {for( i=2;i<NF;i++) printf( " %s", $i)}
      '