Awk 如何在一行中打印重复键列的字段

Awk 如何在一行中打印重复键列的字段,awk,Awk,我想以这样一种方式转换一个表,以便复制 第#2列中的值它将具有第#1列中的相应值 也就是说,像这样的事情 MZ00024296 AC148152.3_FG005 MZ00047079 AC148152.3_FG006 MZ00028122 AC148152.3_FG008 MZ00032922 AC148152.3_FG008 MZ00048218 AC148152.3_FG008 MZ00024680 AC148167.6_FG001 MZ00013456 AC149

我想以这样一种方式转换一个表,以便复制 第#2列中的值它将具有第#1列中的相应值

也就是说,像这样的事情

MZ00024296  AC148152.3_FG005

MZ00047079  AC148152.3_FG006

MZ00028122  AC148152.3_FG008

MZ00032922  AC148152.3_FG008

MZ00048218  AC148152.3_FG008

MZ00024680  AC148167.6_FG001

MZ00013456  AC149475.2_FG003

由于需要在R中进行计算,我尝试使用:

x=aggregate(mz_grmz,by=list(mz_grmz[,2]),FUN=paste(mz_grmz[,1],sep="|"))
但它不工作(功能错误) 匹配中出错。乐趣(乐趣): “粘贴(mz_grmz[,1],sep=“|”)不是函数、字符或符号

我还提醒自己unstack()函数,但它不是我所需要的

根据我的基本知识,我尝试使用awk来完成这项工作,我重新编写了下面给出的代码:

#/垃圾箱/垃圾箱
为了你
awk-v FS=“\t”'{
对于(x=1;x2&&x=x+1){
打印$2“\t”x
}
else{print NR}
}
}“$y>$y.2
完成
不幸的是,它不起作用,它只能生成包含字段#2和一些数字的巨大文件

我想这是一项容易的任务,但现在我的能力还不够。 谁能给我一个提示吗?也许只是在R中聚合使用的函数


谢谢

您可以在awk中这样做:

awk '
    {
        if ($2 in a)
            a[$2] = a[$2] "|" $1
        else
            a[$2] = $1
    }
    END {
        for (i in a)
            print i, a[i]
    }' INFILE > OUTFILE

要使输出与问题中的文本保持一致(空行等):

测试

kent$  echo "MZ00024296  AC148152.3_FG005

MZ00047079  AC148152.3_FG006

MZ00028122  AC148152.3_FG008

MZ00032922  AC148152.3_FG008

MZ00048218  AC148152.3_FG008

MZ00024680  AC148167.6_FG001

MZ00013456  AC149475.2_FG003"|awk '{if($0 &&($2 in a))a[$2]=a[$2]"|"$1;else if ($0) a[$2]=$1;}END{for(x in a){print x,a[x];print ""}}'
AC149475.2_FG003 MZ00013456

AC148152.3_FG005 MZ00024296

AC148152.3_FG006 MZ00047079

AC148152.3_FG008 MZ00028122|MZ00032922|MZ00048218

AC148167.6_FG001 MZ00024680

此GNU-sed解决方案可能适合您:

 sed -r '1{h;d};H;${x;s/(\S+)\s+(\S+)/\2\t\1/g;:a;s/(\S+\t)([^\n]*)(\n+)\1([^\n]*)\n*/\1\2|\4\3/;ta;p};d' input_file

说明:使用扩展正则表达式选项
-r
使正则表达式更具可读性。将整个文件读入保持空间(HS)。然后在文件末尾,切换到HS,首先交换和制表符单独的字段。然后比较相邻行中的第一个字段,如果它们匹配,则将第二条记录中的第二个字段标记为第一行,并用
分隔。重复,直到没有其他相邻行具有重复的第一个字段,然后打印文件。

空行可能会在输出中出现问题。我没有测试,但我可以看到,输出中应该有“| | |…”。顺便说一句,你的声誉号码很好:)4444@Kent我假设空行是复制粘贴工件。如果没有,这可以通过在第一个
{
.schot,Kent之前添加
NF
来轻松解决。谢谢你们两个。它可以工作:-)。空行确实是一个工件。如果不是,我会在主脚本之前使用sed'/^$/d删除它。谢谢Poton的回复。你的代码要么不工作,要么我的计算机(2 x 1.5 GHz,2Gb RAM)太弱了。我已经提交了它,我的系统监视器显示代码正在运行,但大约30分钟后。没有任何变化,所以我终止了进程。无论如何-谢谢你的时间。我检查了较小的文件,它可以工作。它只是比awk代码慢得多。
awk '{if($0 &&($2 in a))a[$2]=a[$2]"|"$1;else if ($0) a[$2]=$1;}\
END{for(x in a){print x,a[x];print ""}}' inputFile
kent$  echo "MZ00024296  AC148152.3_FG005

MZ00047079  AC148152.3_FG006

MZ00028122  AC148152.3_FG008

MZ00032922  AC148152.3_FG008

MZ00048218  AC148152.3_FG008

MZ00024680  AC148167.6_FG001

MZ00013456  AC149475.2_FG003"|awk '{if($0 &&($2 in a))a[$2]=a[$2]"|"$1;else if ($0) a[$2]=$1;}END{for(x in a){print x,a[x];print ""}}'
AC149475.2_FG003 MZ00013456

AC148152.3_FG005 MZ00024296

AC148152.3_FG006 MZ00047079

AC148152.3_FG008 MZ00028122|MZ00032922|MZ00048218

AC148167.6_FG001 MZ00024680
 sed -r '1{h;d};H;${x;s/(\S+)\s+(\S+)/\2\t\1/g;:a;s/(\S+\t)([^\n]*)(\n+)\1([^\n]*)\n*/\1\2|\4\3/;ta;p};d' input_file