【问题标题】:How to extract the ids and keys using linux command?如何使用 linux 命令提取 id 和密钥?
【发布时间】:2021-06-26 06:37:43
【问题描述】:

我有与第二列的键值匹配的 id 列表,我想删除重复项并将相应的值保留为逗号或冒号分隔,如输出格式所示 输入文件

TRINITY_DN728479_c0_g1_i1   GO:0003674
TRINITY_DN728479_c0_g1_i1   GO:0003824
TRINITY_DN728479_c0_g1_i1   GO:0003887
TRINITY_DN728480_c0_g1_i1   GO:0003891
TRINITY_DN728480_c0_g1_i1   GO:0003892

我想要输出

TRINITY_DN728479_c0_g1_i1        GO:0003674, GO:0003824, GO:0003887
TRINITY_DN728480_c0_g1_i1        GO:0003891,GO:0003892

我尝试过 awk 但它不起作用

awk -vORS=, '{ print $2 }' Gene.GO | sed 's/,$/\n/'

【问题讨论】:

  • 请展示您的尝试
  • I have tried awk but it not working out,您好像忘记添加代码了,请务必添加在 SO 中受到高度鼓励的代码,谢谢。
  • 我知道只能用这个命令转换逗号分隔文件中的列 awk -vORS=, '{ print $2 }' Gene.GO | sed 's/,$/\n/'
  • @MathavanMuthaiyan,您的努力没有对错(尝试过的代码),请随时将其添加到您的问题中,非常鼓励您这样做,谢谢。
  • 您永远不需要通过管道将 awk 传递给 sed,反之亦然,产生输出而没有终止换行符的脚本是不好的,因为这是下一个工具的未定义行为(所以不要假设您可以添加当您尝试使用 sed 时,稍后换行),并且使用 -vORS= 是不必要的,在 -v 之后放置一个空格,例如-v ORS=,所以它适用于所有 awks。

标签: linux awk grep


【解决方案1】:

如果输入是 2 列并且已经按列 1 分组

awk '
{
  printf "%s", ($1==p ? "," $2 : ors $0)
  ors = ORS
  p = $1
} END {printf "%s", ors}' file

【讨论】:

  • 很好,尤其是 END 部分,即使是空输入文件也能正常工作。
【解决方案2】:

第一个解决方案:使用您显示的示例,请尝试遵循awk 代码。如果您的第一个字段未排序,请使用 sortawk 代码。

sort -t_ -k1 -k2 Input_file | 
awk '
  BEGIN{ OFS="\t" }
  prev!=$1 && prev{
    print prev,value
    value=""
  }
  {
    value=($1 in value ? value[$1] s1: "")$2
    prev=$1
  }
  END{
    if(prev && value){
      print prev,value
    }
  }
'

第二个解决方案:awk 解决方案,这将按照与第一个字段进入 Input_file 的顺序相同的顺序为您提供输出。

awk '
BEGIN{ s1=","; OFS="\t" }
!arr1[$1]++{
  arr2[++count]=$1
}
{
  value[$1]=($1 in value ? value[$1] s1: "")$2
}
END{
  for(i=1;i<=count;i++){
    print arr2[i],value[arr2[i]]
  }
}
' Input_file

第三种解决方案:如果您不担心输出中第一个字段的顺序,请尝试以下操作。

awk '
BEGIN{ s1=",";OFS="\t" }
{
  value[$1]=($1 in value ? value[$1] s1: "")$2
}
END{
  for(i in value){
    print i, value[i]
  }
}
'  Input_file

【讨论】:

  • 如果您使用变量名称来告诉您它们代表什么而不是它们是如何实现的,那么您的第二个脚本可能会更清晰,例如如果您更改 arr1 -> seenarr2 -> keyscount -> numKeys
  • @Mathavan Muthaiyan,如果我的解决方案对您有用,请告诉我?
【解决方案3】:

datamash:

$ datamash -W -g1 collapse 2 <ip.txt 
TRINITY_DN728479_c0_g1_i1   GO:0003674,GO:0003824,GO:0003887
TRINITY_DN728480_c0_g1_i1   GO:0003891,GO:0003892
  • -W 使用空格/制表符作为字段分隔符
  • -g1 按列分组 1
  • collapse 2 根据列1 键收集2 列中的所有值

如果输入未排序,请使用-s 选项或通过管道从sort 命令输入。输出字段分隔符在此处为制表符,您可以使用--output-delimiter 选项进行更改。

【讨论】:

    猜你喜欢
    • 2019-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-16
    • 1970-01-01
    相关资源
    最近更新 更多