【awk】笔记
2019-01-22 本文已影响2人
caokai001
1.按照指定的列去除重复
awk '!a[$1]++' file
awk ‘! a[$0]++’ 去重
上述命令的意思是,如果第一列有重复,则保留最先出现的值;如果没有重复,则保留该值。($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
如果事先通过排序,将想要的最优值排在前面,则去除重后,得到的即为最优值。
2.拆分文件
如有以下文件:
$ 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
3.行-列转化
3.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"
;而不含有逗号的则照常打印出来。
3.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`的结果打印出来。