查看原文
其他

AWK超详细讲解

小师 百迈客医学 2023-03-27

当你拿到一个超大的表格文件,excel打不开怎么办?几百万行的数据,根本无从下手,怎么快速筛选定位出你想要的信息?你是不是也有过这样的烦恼?今天小编就带你一行命令解决它!

接触过Linux的应该都知道,AWK是一款高效的文本处理工具,它与grep和sed一起被称为Linux三大剑客。虽然awk也是流式编辑器的一种,是一行一行的读取并处理文件,但确能实现一些基于列的操作,实现类似Windows下,excel表格的一些功能。下面介绍一下awk的入门知识以及一些比较频繁的用法,让你在面对大量文本,各种稀奇复杂的处理需求时,也能游刃有余~
 

awk的基本语法如下:

awk [option] 'BEGIN{action} {actionEND{action}' infile


为了便于讲解和理解,将基本语法简单分为以下四个语句块:


option语句块:指定参数。常用的参数一般只有-F这一个,用于指定输入分隔符,可以理解为用于分隔文件中的各列。


BEGIN语句块:在读取输入文件之前,执行该语句块后{}中的action操作。常用于设定一些变量的起始值等。


BODY语句块:中间的{}是awk的核心部分,awk会对输入文件中的每一行都执行一遍{}中的action操作。


END语句块:在整个输入文件读取处理完成之后,执行该语句块后{}中的action操作。常用于一些统计输出。

因此awk的工作流程可以简单理解为:首先读文件前执行BEGIN语句块,然后一行一行的读入文件,每读入一行执行一遍BODY语句块,最后读完文件的所有行之后再执行END语句块。

 

例如,现有一个基因表达量表格gene.xls如下,表格中各列以tab制表符分隔:

如果想要打印将该文件按照ABCD的顺序进行打印,使用cut是不行的,因为cut不会改变文件列的顺序,此时可以使用如下awk命令:
awk -F '\t' '{print $1"\t"$5"\t"$3"\t"$4"\t"$2}' gene.xls

其中-F参数用于指定输入文件的分隔符,默认以空格或者制表符进行分隔,也就是当文件中同时存在空格和制表符时,awk都会进行分隔,所以最好是加上该参数,指定以制表符进行分隔。分隔后的每一个字符串为一个字段,各个字段也就是每一行的各列,使用$符号加列序号来调用某列,比如第一列就是$1($0表示整行的所有内容)。

你会发现,当有较多列需要打印时,每两列中间都需要加上"\t"来进行分隔,很是麻烦。此时就可以用到awk中的一个内置变量OFS,它用来指定输出分隔符,默认输出分隔符为空格。因此上述命令就可以改成:

awk -F '\t' 'BEGIN{OFS="\t"}{print $1,$5,$3,$4,$2}' gene.xls

awk中有很多好用的内置变量,除了上面讲到的OFS外,常用的还有如下几个:


ARGIND:当前文件的个数,适用于处理多个文件时;
FNR:当前文件的当前行数,从1开始;
NR:已经读取的总行数,从1开始;
NF:当前处理行的列数;

awk的常见用法如下:
1. 匹配输出
例:输出包含“newgene”字符的行
awk -F '\t' '{if($0~/newgene/){print}}' gene.xls
#或简写为:
awk -F '\t' '/newgene/' gene.xls

awk中的控制语句与C语言类似,如上述的if语句,其基本结构为 `if(pattern){action}else{action}`。且awk也支持正则匹配,在这里就不细讲了。


2. 条件过滤

例:过滤掉A和B样本中表达量少于0.5的基因

awk -F '\t' '{if($5 > 0.5 && $3 > 0.5){print}}' gene.xls


awk支持各种关系运算符:不等于!=、等于==、大于>、小于<、大于等于>=、小于等于<=、逻辑与&&、逻辑或|| 等。


3. 数据统计

例:统计基因的表达量综合

#统计每个基因在各样本的表达量总和,即对行求和
awk -F '\t' 'NR>1{sum=0;for(i=2;i<=NF;i++){sum+=$i};print $1"\t"sum}' gene.xls
#统计每个样本中各基因的表达量总和,即对列求和
awk -F '\t' 'NR==1{for(i=2;i<=NF;i++){sample[i]=$i}}NR>1{for(i=2;i<=NF;i++){num[i]+=$i}}END{for(j in sample){print sample[j]"\t"num[j]}}' gene.xls

这里涉及到awk中的另一种数据类型:数组。数组的使用非常灵活,它不需要提前定义,可以随时扩展,下标可以是数据也可以是字符串。可以类比perl中的哈希,python中的字典。


4. 多文件匹配输出

例:输出指定基因名在各个样本中的表达量情况


#指定基因名文件如下
cat id.txt
 gene3
 gene5
 newgene2
#awk匹配输出
awk -F '\t' 'NR==FNR{a[$1]}NR>FNR{if(FNR==1 || $1 in a){print $0}}' id.txt gene.xls
#或者
awk -F '\t' 'NR==FNR{if(FNR==1){print}a[$1]=$0}NR>FNR{print a[$1]}' gene.xls id.txt

当给awk提供多个文件时,它会按照提供文件的顺序依次一行行的读入。这里给了两个文件,主要依靠NR和FNR这两个内置变量来区分当前读取的是哪一个文件。前面提到,NR表示当前一共读取的行数,FNR表示读取的当前文件的当前行数,也就是当读取第二个文件的第一行时,FNR的值为1,而NR的值为第一个文件的行数加一。所以,当NR==FNR时,表示正在读取第一个文件,而当NR>FNR时,则表示正在读取第二个文件。

因此,上述第一种写法是先读取指定基因名的文件,将需要提取的基因名存入a这个数组中,当读取第二个文件即表达量文件时,判断第一列是否存在于a这个数组中,如果存在就输出当前行。另外,为了保留表达量文件的表头,这里的if判断中还有一个条件是FNR==1,即处于表达量文件第一行时,直接输出。上述第二种写法是先读取表达量文件,将基因名作为下标,当前行作为值,存入a这个数组中,当读取第二个文件即指定基因名的文件时,使用文件中的基因名去a数组中提取对应的值。同样的,为了保留表达量文件的表头,添加了if(FNR==1){print}这个语句。

但是,当输入文件是三个及以上时,上述通过NR和FNR来处理的办法就行不通了,这时,可以利用另一个内置变量ARGIND。

awk -F '\t' 'ARGIND==1{a[$1]}ARGIND==2{a[$1]}ARGIND==3{if(FNR==1 || $1 in a){print $0}}' id.txt id2.txt gene.xls

除了上文中提到的awk的功能外,它还有很多强大的功能,比如一些内置的函数如sub替换,length统计字符串长度,split切割字符串等等。快去试试吧,你也能成为awk文本处理高手!





一切好玩的尽在百迈客云端,小程序、小命令快速解决你的忧愁与烦恼,快快来百迈客云,百迈客云平台(BMKCloud)实现你零基础分析的所有梦想!


 

往期回顾:

肿瘤突变数据分析神器:maftools

【实用贴】快速上手批量可视化助您完美作图

【实用贴】原始数据上传SRA新版流程

【实用帖】手把手教你如何上传GEO数据库

一键解密MD5值-您的数据完整吗?

柱形图看腻了?不如试试这个

【实用贴】小而强悍的截图神器——snipaste


文:小师
排版:市场部


干货|百迈客单细胞 & 空间转录组专题系列

百迈客生物基于高通量测序技术、生物信息分析技术和生物云计算技术,为广大科研工作者提供以综合技术服务、生物云分析、三代高通量测序以及试剂、仪器等科研周边业务。

公司拥有Nanopore、PacBio、Illumina、Waters、10XGenomics等主流服务平台,以及基于云架构的生物云计算平台—百迈客云,提供涵盖人重外显子、三维基因组、单细胞与空间转录组、基因组组装、转录调控、微生物、群体遗传、质谱及表观遗传等研究方向的技术服务。目前百迈客云平台拥有200多款基因分析工具,分析结果可直接用于文章发表,更有近百部科研相关视频和8大基因数据库助力科研工作者深度数据挖掘。

自公司成立起先后在《Cell》、《Nature》、《Nature Genetics》、《Nature Communications》、《Plant Cell》等学术刊物发表论文数千篇,拥有国家发明专利技术40余项,软件著作权近200余项。

我们一直秉承”生物科技创新,服务社会,造福人民”的企业使命,致力于打造“生物科技创新中心”的发展愿景,让生物科技更快,更好的提高人类生活质量。


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存