前言
??对于用Linux来处理数据的用户来说,应该都知道Linux处理数据的三个强有力的命令awk、sed、grep——人称三??汀D敲唇裉煜敫蠹曳窒硪桓銎渲械囊桓雒頰wk,为什么要跟大家分享这个命令呢?因为有时候我们需要做的事情很简单,不知道去写一个脚本,那就可以用一行命令来解决。awk用来干这些事情可以说是非常适合,因为awk可以做很多事情如匹配、切割、转置,甚至还可以在其内部写循环,用的好的话可以提高工作效率。今天我们来说一下三种常见情形下,如何方便快速的用awk一行代码来解决。
??下面我们来简单介绍一下awk的语法,完整的语法为:awk [optional] 'BEGIN{...}{...}END{...}' file/stdin。awk可用直接读取文件的内容也可以接受来至标准输入的内容,有了这个特性结合管道“|”来使用更加方便。在命令行可以查看awk可以接受的全部选项(如下所示),其实大部分我也没用过,感兴趣可以自己摸索一番,最常用的两个选项就是-F、-v,-F后面接的参数是用来分割内容的分隔符,-v 后面接的参数是awk外部的一个变量。
awk --help
Usage: awk [POSIX or GNU style options] -f progfile [--] file ...
Usage: awk [POSIX or GNU style options] [--] 'program' file ...
POSIX options: GNU long options: (standard)
-f progfile --file=progfile
-F fs --field-separator=fs
-v var=val --assign=var=val
Short options: GNU long options: (extensions)
-b --characters-as-bytes
-c --traditional
-C --copyright
-d[file] --dump-variables[=file]
-e 'program-text' --source='program-text'
-E file --exec=file
-g --gen-pot
-h --help
-L [fatal] --lint[=fatal]
-n --non-decimal-data
-N --use-lc-numeric
-O --optimize
-p[file] --profile[=file]
-P --posix
-r --re-interval
-S --sandbox
-t --lint-old
-V --version
1、获取想要的列
??下面我们来通过具体的场景展现awk的能力,首先来看一下如何使用awk来分割内容获取想要的部分。例如这里有个文件总共9列,分隔符为制表符,但值得注意是第一列的内容为Ensembl ID和Symbol ID两部分组成,其中分隔符为空格,内容如下所示:
gene C293T igf Igf2bp2 InputI InputP ptbp Ptbp1 S293T
ENSG00000000003.15 TSPAN6 4.893 6.088 5.516 5.033 4.853 5.391 5.705 4.862
ENSG00000000005.6 TNMD 0.343 0 0 0.3872 0.3346 0 0 0.6902
ENSG00000000419.12 DPM1 4.529 4.691 4.685 4.554 4.375 2.234 4.394 4.372
ENSG00000000457.14 SCYL3 1.841 2.571 3.002 2.176 2.011 1.565 2.255 1.879
ENSG00000000460.17 C1orf112 3.431 4.441 4.324 3.674 3.618 2.611 3.857 3.652
ENSG00000000938.13 FGR 0 0 0 0 0.02306 0.07593 0 0
ENSG00000000971.16 CFH 0.1248 0.3185 0.01851 0.1209 0.1302 0.1272 0.006274 0.1486
ENSG00000001036.14 FUCA2 4.774 5.482 5.887 4.805 4.812 4.35 5.494 4.785
ENSG00000001084.13 GCLC 4.393 3.463 5.523 4.408 4.586 2.699 4.827 4.571
ENSG00000001167.14 NFYA 4.127 4.392 5.601 4.247 4.233 2.392 4.011 4.084
ENSG00000001460.18 STPG1 3.958 4.261 4.496 3.924 3.947 2.158 3.547 3.925
那我们来看如何提取想要的列,示例代码如下:
#提取前三列的内容到新文件里
awk -F"\t" '{OFS="\t";print$1,$2,$3}' zhaoy_log2TPM.txt >new.txt
#因为输入和输出的分隔符一致,上面的命令还可以写成
awk '{OFS=FS="\t";print$1,$2,$3}' zhaoy_log2TPM.txt >new.txt
#查看新文件内容
head nex.txt
gene C293T igf
ENSG00000000003.15 TSPAN6 4.893 6.088
ENSG00000000005.6 TNMD 0.343 0
ENSG00000000419.12 DPM1 4.529 4.691
ENSG00000000457.14 SCYL3 1.841 2.571
ENSG00000000460.17 C1orf112 3.431 4.441
??你以为这样就结束了么,awk还可以更厉害一点,还拿上面文件来说,我现在还是要前3列,但是第一列我只要Ensembl ID,那么该如何实现呢?请看下面示例代码:
#以制表符和空格一起作为分割符来分割内容
awk -F "[\t ]" 'BEGIN{print"gene\tC293T\tigf"}{OFS="\t";if(NR>1)print$1,$3,$4}' zhaoy_log2TPM.txt >new.txt
#查看内容
gene C293T igf
ENSG00000000003.15 4.893 6.088
ENSG00000000005.6 0.343 0
ENSG00000000419.12 4.529 4.691
ENSG00000000457.14 1.841 2.571
ENSG00000000460.17 3.431 4.441
ENSG00000000938.13 0 0
ENSG00000000971.16 0.1248 0.3185
ENSG00000001036.14 4.774 5.482
ENSG00000001084.13 4.393 3.463
??是不是很方便,awk可以同时接受多个分隔符,这个功能就更厉害了,即使用来处理gtf文件也是可以的。用好了可以一行命令解决大部分的文件。
2、两个文件匹配
??有时候我们想要根据两个文件共有列的内容来合并两个文件,这个适合如何用一行代码来完成呢?例如我有两个文件内容如下:
#文件test1.txt
gene C293T igf
ENSG00000000003.15 4.893 6.088
ENSG00000000005.6 0.343 0
ENSG00000000419.12 4.529 4.691
ENSG00000000457.14 1.841 2.571
ENSG00000000460.17 3.431 4.441
#文件test2.txt
gene Igf2bp2 Igf2bp2
ENSG00000000003.15 5.516 5.033
ENSG00000000005.6 0 0.3872
ENSG00000000419.12 4.685 4.554
ENSG00000000457.14 3.002 2.176
ENSG00000000460.17 4.324 3.674
??可以看到上面两个文件有共同的列,那么我们如何根据这个共同的列来匹配合并两个文件呢?请看下面的代码:
#根据第一列来合并两个文件
awk 'NR==FNR{OFS=FS="\t";a[$1]=$2FS$3;next}{if($1 in a)print$0,a[$1]}' test1.txt test2.txt >merge.txt
#查看合并的内容
gene Igf2bp2 InputI C293T igf
ENSG00000000003.15 5.516 5.033 4.893 6.088
ENSG00000000005.6 0 0.3872 0.343 0
ENSG00000000419.12 4.685 4.554 4.529 4.691
ENSG00000000457.14 3.002 2.176 1.841 2.571
ENSG00000000460.17 4.324 3.674 3.431 4.441
ENSG00000000938.13 0 0 0 0
是不是很方便,有了这个功能,提取匹配两个文件来提取内容,只用一行代码就可以搞定,分分钟的事!
3、文件转置
??有时候需要将文件行和列转置,这个时候也可以用awk来完成,同样是一行代码即可搞定。就拿上面的test1.txt文件来做示范,示例代码如下:
#转置文件
awk '{for(i=1;i<=NF;i++){a[FNR,i]=$i}}END{for(i=1;i<=NF;i++){for(j=1;j<=FNR;j++){printf a[j,i]"\t"}print ""}}' test1.txt >zhuanzhi.txt
#查看转置后的文件
gene ENSG00000000003.15 ENSG00000000005.6 ENSG00000000419.12 ENSG00000000457.14
C293T 4.893 0.343 4.529 1.841
igf 6.088 0 4.691 2.571
??转置文件用awk来做也是分分钟的事,用awk来处理数据有时候真的是省时省力,现在是不是觉得awk很给力,其实它还有很多功能,学好了可以用来做很多的事。对于没有编写脚本需求的事来说,用awk命令行来解决,一行代码方便快捷。
最后
??emm,今天就分享到这里,现在是不是觉得awk这个命令很实用,赶快用起来吧!