专栏名称: 生信百科
依托高校科研平台,面向生物信息科研工作者。生物信息学习资料;常见数据分析技巧、流程;公共数据库分享;科研思路分享;
目录
相关文章推荐
解螺旋  ·  IF ... ·  昨天  
医脉通临床指南  ·  老年慢性呼吸系统疾病人群如何接种流感疫苗? ·  1 周前  
51好读  ›  专栏  ›  生信百科

awk使用技巧

生信百科  · 公众号  · 医学  · 2017-08-08 07:00

正文

复习:

Linux文本处理三剑客之awk

按照指定的列去除重复

awk '!a[$1]++' file


上述命令的意思是,如果第一列有重复,则保留最先出现的值;如果没有重复,则保留该值。($1表示第一列,如果想对第二列进行处理,则$2,以此类推)如:

$ cat example.txt

MA_100472g0010  MA_100472       91.67   492     0       1       1       451     19718   21193   0.0     813

MA_100472g0010  MA_100472       82.84   134     14      2       446     572     22465   22860   6e-59   226

MA_8348g0030    MA_10059887     38.44   666     369     16      20      655     4782    2818    1e-101  350

MA_99999g0010   MA_10430467     51.37   146     69      1       1       146     20468   20899   3e-30   125

MA_99999g0010   MA_36290        47.06   136     72      0       1       136     8905    8498    3e-23   10

去除重复后:

$ awk '!a[$1]++' example.txt

MA_100472g0010  MA_100472       91.67   492     0       1       1       451     19718   21193   0.0     813

MA_8348g0030    MA_10059887     38.44   666     369     16      20      655     4782    2818    1e-101  350

MA_99999g0010   MA_10430467     51.37   146     69      1       1       146     20468   20899   3e-30   125

如果事先通过排序,将想要的最优值排在前面,则去除重后,得到的即为最优值。

拆分文件

如有以下文件:

$ head TAIR10_GFF3.gff

1       TAIR10  gene    3631    5899    .       +       .       ID=AT1G01010;Note=protein_coding_gene;Name=AT1G01010

1       TAIR10  mRNA    3631    5899    .       +       .       ID=AT1G01010.1;Parent=AT1G01010;Name=AT1G01010.1;Index=1

1       TAIR10  exon    3631    3913    .       +       .       Parent=AT1G01010.1

1       TAIR10  five_prime_UTR  3631    3759    .       +       .       Parent=AT1G01010.1

1       TAIR10  CDS     3760    3913    .       +       0       Parent=AT1G01010.1,AT1G01010.1-Protein;

1       TAIR10  exon    3996    4276    .       +       .       Parent=AT1G01010.1

1       TAIR10  CDS     3996    4276    .       +       2       Parent=AT1G01010.1,AT1G01010.1-Protein;

1       TAIR10  exon    4486    4605    .       +       .       Parent=AT1G01010.1

1       TAIR10  CDS     4486    4605    .       +       0       Parent=AT1G01010.1,AT1G01010.1-Protein;

1       TAIR10  exon    4706    5095    .       +       .       Parent=AT1G01010.1

按第三列进行拆分:

awk '{print > $3}' TAIR10_GFF3.gff

得到:

$ ls -lh

total 72M

-rw-rw-r-- 1 liuhui liuhui  15M Aug 5 13:58 CDS

-rw-rw-r-- 1 liuhui liuhui  12M Aug 5 13:58 exon

-rw-rw-r-- 1 liuhui liuhui 2.2M Aug 5 13:58 five_prime_UTR

-rw-rw-r-- 1 liuhui liuhui 2.5M Aug 5 13:58 gene

-rw-rw-r-- 1 liuhui liuhui 3.2M Aug 5 13:58 mRNA

-rw-rw-r-- 1 liuhui liuhui  36M Aug 5 13:58 TAIR10_GFF3.gff

-rw-rw-r-- 1 liuhui liuhui 2.0M Aug 5 13:58 three_prime_UTR

$ head -n 3 CDS

1       TAIR10  CDS     3760   3913   .       +       0      Parent=AT1G01010.1,AT1G01010.1-Protein;

1       TAIR10  CDS     3996   4276   .       +       2      Parent=AT1G01010.1,AT1G01010.1-Protein;

1       TAIR10  CDS     4486   4605   .       +       0      Parent=AT1G01010.1,AT1G01010.1-Protein;

$ head -n 3 exon

1       TAIR10  exon   3631   3913   .       +       .       Parent=AT1G01010.1

1       TAIR10  exon   3996   4276   .       +       .       Parent=AT1G01010.1

1       TAIR10  exon   4486   4605   .       +       .       Parent=AT1G01010.1

行-列转化

1. 一行变多行

需要将如下格式转换成“一个基因号对应一个 GO 号”

$ cat pta_go.txt

PITA_000018514-RA GO:0003700,GO:0005634,GO:0006355,GO:0043565

PITA_000094612-RA GO:0005618,GO:0006073,GO:0016762,GO:0048046

PITA_000087838-RA GO:0008762,GO:0016491,GO:0050660,GO:0055114

PITA_000082501-RA       GO:0003824,GO:0008152

PITA_000063616-RA       GO:0030247

可以这样:

$ awk '{gsub(/,/, "\n"$1"\t");print}' pta_go.txt > pta_go.annot

$ cat pta_go.annot

PITA_000018514-RA GO:0003700

PITA_000018514-RA       GO:0005634

PITA_000018514-RA       GO:0006355

PITA_000018514-RA       GO:0043565

PITA_000094612-RA GO:0005618

PITA_000094612-RA       GO:0006073

PITA_000094612-RA       GO:0016762

PITA_000094612-RA       GO:0048046

PITA_000087838-RA GO:0008762

PITA_000087838-RA       GO:0016491

PITA_000087838-RA       GO:0050660

PITA_000087838-RA       GO:0055114

PITA_000082501-RA       GO:0003824

PITA_000082501-RA       GO:0008152

PITA_000063616-RA       GO:0030247

原理就是将所有的逗号 , 依次替换成 "\n"$1"\t";而不含有逗号的则照常打印出来。

2. 多行变一行

$ awk '{a[$1]=($1 in a ? a[$1]","$2 : $0)} END{for (k in a) print a[k]}' pta_go.annot

PITA_000018514-RA GO:0003700,GO:0005634,GO:0006355,GO:0043565

PITA_000082501-RA       GO:0003824,GO:0008152

PITA_000094612-RA GO:0005618,GO:0006073,GO:0016762,GO:0048046

PITA_000063616-RA       GO:0030247

PITA_000087838-RA GO:0008762,GO:0016491,GO:0050660,GO:0055114


即将文件 pta_go.annot 的格式转成文件 pta_go.txt 的格式

这里用到了三目运算符?:? 代表,而: 代表。如:

$ awk 'BEGIN{a="b";print a=="b" ? "ok" : "err"}' # 变量 a 与字符“b”相同

ok

$ awk 'BEGIN{a="b";print a=="c" ? "ok" : "err"}' # 变量 a 与字符“c”不相同

err

所以,语句

a[$1]=($1 in a ? a[$1]","$2 : $0)

的含义是:$1 如果是第一次出现,将$0存入数组a中,数组的下标是$1;如果$1在数组 a 中,表明其出现两次或以上时,则将a[$1](代表之前的 $0)和 $2 存入数组 a 中(即更新数组)。

当该语句执行完毕后,执行 END 语句块,将数组a的结果打印出来。


未完待续~