我有一个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应该基于以下方式排序:
字母顺序
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
”...
AlleleA
和AlleleB
列,以便如果任一列包含多于1个字母,则在newID
列中,它将位于第一位。如果两列中只有一个字母,则这些字母按字母顺序排列在newID
列
答案 0 :(得分:1)
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
返回替换结果答案 1 :(得分: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