【问题标题】:combining multiple column values in lines based on identical column基于同一列在行中组合多个列值
【发布时间】:2014-10-30 19:17:58
【问题描述】:

我需要帮助来改进我的工作代码,以便根据指定列的相同值组合多行。 这是一个示例数据:

c-i1_pos-at1-v2 162a    AT1G01040.1 2   3422-3443   3433    1
c-i1_pos-at1-v2 162b    AT1G01040.1 2   3422-3443   3433    1
pare-i_226-v2-wt    162a    AT1G01040.1 2   3422-3443   3433    0
pare-i_226-v2-wt    162b    AT1G01040.1 2   3422-3443   3433    0
xrn4-pare-i_ath-227-v2-wt   827 AT1G02860.1 1   258-278 269 1
i2_lib2-v2  156a    AT1G03730.1 4   242-260 252 3
i2_lib2-v2  156b    AT1G03730.1 4   242-260 252 3
i2_lib2-v2  156c    AT1G03730.1 4   242-260 252 3
i2_lib2-v2  156d    AT1G03730.1 4   242-260 252 3
i2_lib2-v2  156e    AT1G03730.1 4   242-260 252 3

基本上如果 $3,$5 列中的值相同,我想将列 $2,$6(或更多)的行合并,其余列的唯一值合并如下:

AT1G01040.1 3422-3443   3433    162a,162b
AT1G02860.1 258-278 269 827
AT1G03730.1 242-260 252 156a,156b,156c,156d,156e

现在我正在尝试根据答案here 分多个步骤执行此操作。

awk 'BEGIN{FS=OFS="\t"} {c=$2 FS $3 FS $5; if (c in a) a[c]=a[c]","$6; else a[c]=$6}END{for (k in a) print k,a[k]}'|awk '{p=$1 FS $2 FS $4; if (p in l) l[p]=l[p]","$3;else l[p]=$3}END{for (m in l) print m,l[m]}' <input.txt

这给出了:

AT1G01040.1 3422-3443   3433,3433   162a,162b
AT1G02860.1 258-278 269 827
AT1G03730.1 242-260 252 156a,156b,156c,156d,156e

我认为我应该将剩余列中的值作为数组放入,以便一步获得所需的输出,但我正在努力找出正确的上下文。

【问题讨论】:

  • 理想情况下,第 1 行应该只有一个 3433,但是我上面的代码打印 3433 两次..一定是因为我搞砸了一些东西:/
  • 是的,它工作得很好——非常感谢!现在我正在通过代码来理解正确的上下文——再次感谢。
  • 那会很棒:)
  • @pasaima 我已经添加了解释。希望现在很清楚:)

标签: bash awk


【解决方案1】:

怎么样

awk '{if ( $3 in a ) a[$3] = a[$3]","$2; else a[$3] = $3" "$5" "$6" "$2} END{for (i in a) print a[i]}' inputFile

将产生输出为

AT1G03730.1 242-260 252 156a,156b,156c,156d,156e
AT1G02860.1 258-278 269 827
AT1G01040.1 3422-3443 3433 162a,162b,162a,162b

说明

a[$3] = $3" "$5" "$6" "$2 创建一个数组a,以第三个字段$3 为索引,else 部分确保在第一次遇到该行时创建该数组。

if ( $3 in a ) a[$3] = a[$3]","$2 如果第三个字段$3 已经存在于数组中,则将第二个字段$2 添加到数组中

END{for (i in a) print a[i]} END 块在输入结束时被执行。打印整个数组并给出输出

编辑

一个更简单的版本是

awk '{( $3 in a ) ? a[$3] = a[$3]","$2 : a[$3] = $3" "$5" "$6" "$2} END{for (i in a) print a[i]}' inputFile

感谢 Jotne 的建议。

【讨论】:

  • 一些打高尔夫球的代码:awk '{a[$3]=($3 in a)?a[$3]","$2:$3FS$5FS$6FS$2} END {for (i in a) print a[i]}' file
  • 不客气。您也可以删除括号,但这会使其更难阅读,因此最好将其保留在那里。
  • @Jotne OP 刚开始使用 awk,我们不想让他变得更难:)
猜你喜欢
  • 2019-12-30
  • 2021-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-02
  • 1970-01-01
  • 2015-01-09
相关资源
最近更新 更多