Linux: 數(shù)據(jù)處理三劍客之a(chǎn)wk

前言

??對于用Linux來處理數(shù)據(jù)的用戶來說,應該都知道Linux處理數(shù)據(jù)的三個強有力的命令awk、sed、grep——人稱三劍客。那么今天想跟大家分享一個其中的一個命令awk,為什么要跟大家分享這個命令呢?因為有時候我們需要做的事情很簡單,不知道去寫一個腳本,那就可以用一行命令來解決。awk用來干這些事情可以說是非常適合,因為awk可以做很多事情如匹配、切割、轉置,甚至還可以在其內(nèi)部寫循環(huán),用的好的話可以提高工作效率。今天我們來說一下三種常見情形下,如何方便快速的用awk一行代碼來解決。

??下面我們來簡單介紹一下awk的語法,完整的語法為:awk [optional] 'BEGIN{...}{...}END{...}' file/stdin。awk可用直接讀取文件的內(nèi)容也可以接受來至標準輸入的內(nèi)容,有了這個特性結合管道“|”來使用更加方便。在命令行可以查看awk可以接受的全部選項(如下所示),其實大部分我也沒用過,感興趣可以自己摸索一番,最常用的兩個選項就是-F、-v,-F后面接的參數(shù)是用來分割內(nèi)容的分隔符,-v 后面接的參數(shù)是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、獲取想要的列

??下面我們來通過具體的場景展現(xiàn)awk的能力,首先來看一下如何使用awk來分割內(nèi)容獲取想要的部分。例如這里有個文件總共9列,分隔符為制表符,但值得注意是第一列的內(nèi)容為Ensembl ID和Symbol ID兩部分組成,其中分隔符為空格,內(nèi)容如下所示:

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

那我們來看如何提取想要的列,示例代碼如下:

#提取前三列的內(nèi)容到新文件里
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
#查看新文件內(nèi)容
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還可以更厲害一點,還拿上面文件來說,我現(xiàn)在還是要前3列,但是第一列我只要Ensembl ID,那么該如何實現(xiàn)呢?請看下面示例代碼:

#以制表符和空格一起作為分割符來分割內(nèi)容
awk -F "[\t ]" 'BEGIN{print"gene\tC293T\tigf"}{OFS="\t";if(NR>1)print$1,$3,$4}' zhaoy_log2TPM.txt >new.txt
#查看內(nèi)容
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、兩個文件匹配

??有時候我們想要根據(jù)兩個文件共有列的內(nèi)容來合并兩個文件,這個適合如何用一行代碼來完成呢?例如我有兩個文件內(nèi)容如下:

#文件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

??可以看到上面兩個文件有共同的列,那么我們?nèi)绾胃鶕?jù)這個共同的列來匹配合并兩個文件呢?請看下面的代碼:

#根據(jù)第一列來合并兩個文件
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
#查看合并的內(nèi)容
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

是不是很方便,有了這個功能,提取匹配兩個文件來提取內(nèi)容,只用一行代碼就可以搞定,分分鐘的事!

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來處理數(shù)據(jù)有時候真的是省時省力,現(xiàn)在是不是覺得awk很給力,其實它還有很多功能,學好了可以用來做很多的事。對于沒有編寫腳本需求的事來說,用awk命令行來解決,一行代碼方便快捷。

最后

??emm,今天就分享到這里,現(xiàn)在是不是覺得awk這個命令很實用,趕快用起來吧!

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容