【问题标题】:bash sort and paste columns in alphabetical orderbash 按字母顺序对列进行排序和粘贴
【发布时间】:2017-05-24 19:05:27
【问题描述】:

我有一个file.txt,其中包含以下列

id  chr pos alleleA alleleB
1   01  1234    CT  T
2   02  5678    G   A
3   03  8901    T   C
4   04  12345   C   G
5   05  567890  T   A

我正在寻找一种创建新列的方法,使其看起来像:chr:pos:alleleA:alleleB 问题是 alleleA 和 alleleB 应该基于以下排序: 1. 字母顺序 2. 每行有更多字母的这两列中的任何一列都应该是第一列,然后是第二列

在这个例子中,它看起来像这样:

id  chr pos alleleA alleleB newID
1   01  1234    CT  T   chr1:1234:CT:T
2   02  5678    G   A   chr2:5678:A:G
3   03  8901    T   C   chr3:8901:C:T
4   04  12345   C   G   chr4:12345:C:G
5   05  567890  T   A   chr5:567890:A:T

感谢任何帮助和建议。谢谢。

编辑 到目前为止,我可以修改chr 列,使其看起来像“chr:1”...

AlleleAAlleleB 列应该组合起来,这样如果任一列包含超过 1 个字母,则在 newID 列中它会排在第一位。如果两列中只有一个字母,则这些字母在newID列中按字母顺序排列

【问题讨论】:

  • 你自己尝试了什么?
  • 请详细说明订购。您的样本没有说明问题,因为按字母顺序对等位基因进行排序足以获得所需的输出。

标签: bash awk


【解决方案1】:

gawk 解决方案:

awk 'function custom_sort(i1,v1,i2,v2){   # custom function to compare 2 crucial fields
         l1=length(v1); l2=length(v2);    # getting length of both fields
         if (l1 == l2) { 
             return (v1 > v2)? 1:-1  # compare characters if field lengths are equal
         } else { 
             return l2 - l1          # otherwise - compare by length (descending)
         }   
     } NR==1 { $0=$0 FS "newID" }  # add new column
       NR>1 { a[1]=$4; a[2]=$5; asort(a,b,"custom_sort"); # sort the last 2 columns using function `custom_sort`
       $(NF+1) = sprintf("chr%s:%s:%s:%s",$1,$3,b[1],b[2])
     }1' file.txt | column -t

输出:

id  chr  pos     alleleA  alleleB  newID
1   01   1234    CT       T        chr1:1234:CT:T
2   02   5678    G        A        chr2:5678:A:G
3   03   8901    T        C        chr3:8901:C:T
4   04   12345   C        G        chr4:12345:C:G
5   05   567890  T        A        chr5:567890:A:T

【讨论】:

  • 斯帕西博! awk 是我真正想要的 :)
  • @ThePooh,будьласка! )
  • Prosti,一个 esli u menya bolshe chem 5 列,我如何在没有 sprintf 的情况下自动打印它们? :)
  • @ThePooh, sprintf даёт нам более наглядное и гибкое форматирование, иначе прийдётся брать в кавычки каждель
  • t.e. sprintf vse 列vozmet?
【解决方案2】:

Perl 的救援:

perl -lane '
    if (1 == $.) { print "$_ newID" }
    else { print "$_ ", join ":", "chr" . ($F[1] =~ s/^0//r),
                                  $F[2],
                                  sort { length $b <=> length $a
                                         or $a cmp $b
                                  } @F[3,4];
    }' -- input.txt
  • -l 从输入中删除换行符并将它们添加到 print
  • -n逐行读取输入
  • -a 将空格上的每个输入行拆分到 @F 数组中
  • $. 是输入的行号,条件只是打印第一行的标题
  • s/^0// 从 $F[1] 中删除初始零(即第 2 列)
  • /r 返回替换结果
  • 比较最后两列的长度,如果相同,则使用字符串比较。

【讨论】:

  • 非常感谢您的解释!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-29
  • 1970-01-01
  • 1970-01-01
  • 2013-05-02
  • 2014-02-08
  • 1970-01-01
  • 2017-05-22
相关资源
最近更新 更多