awk
ls | awk -F "." '{print $1}'|xargs -I '{}' mv ./{}.sh ./{}.txt
匹配sh后缀,替换成txt
awk 'NR>=31&&NR<=35'
cat uniprot_sprot.fasta | grep ">" | awk -F " " '{$1="";print $0}' | head
去除第一列,输出第二列到最后一列
最后一列 $NF
介绍
- 和cut比较:cut也可以选择列,但不能重新排列,或计算新的值
# Cutting columns 1,3, and 4.
samtools view demo.bam | cut -f 1,3,4 | head
# With awk we can cut out and rearrange the columns
# and we can compute the actual likelihoods from the MAPQ quality
samtools view demo.bam | awk '{ print $3, $2, $1, 10^(-$5/10) }' | head
-
awk如何工作
awk 'CONDITION { ACTIONS }'
awk 'CONDITION1 { ACTIONS1 } CONDITION2 { ACTIONS2 } CONDITION3 { ACTIONS3 }'
比如,我们可以设定一个条件,输入的第5列要小于40,就打印
samtools view demo.bam | awk '$5 < 60 { print $5 }' | head
-
awk可能出现的问题
大部分空格都可以识别,因为当制表符分隔的文件某一列为空时,会错位。因此最好每次都定义制表符分隔,或设置到bashrc中。
awk -F '\t'
alias awk="awk -F '\t'"
-
一些特定符号
$0 原始的整行
NF number of columns
NR line number
OFS output fields separator
FNR file line number(如果在两个文档上运行,line number会在第二个文件的时候reset到1再开始) -
BEGIN和END
任何在BEGIN之后列出的操作(在{}内)将在Unix awk开始扫描输入之前执行,而END之后列出的操作将在扫描完全部的输入之后执行。因此,通常使用BEGIN来显示变量和预置(初始化)变量,使用END来输出最终结果。
samtools view -f 2 demo.bam | awk ' $9 > 0 { sum = sum + $9; count=count + 1 } END { print sum/count } '
在结束运算后一次性输出
但其实用datamash更简单
samtools view -f 2 demo.bam | awk ' $9 > 0 { print $9 } ' | datamash mean 1
awk还是仅仅只用来选择满足条件的行最好。 -
复杂的条件
> or <
:'$1 < 60 { print 41 }'
==, !=
:'{ $1 == "ORF" { print $1 }'
~, !~
匹配或不匹配(正则表达式):' $1 ~ "YALC|YALW" { print $1 }'
匹配 pattern另一种方法是将pattern用/包围, 称为regexp constant:' $1 ~ /YALC|YALW/ { print $1 }'
-
输出格式
修改OFS,分隔符为制表符
echo | awk '{ OFS="\t"; print 1,2,3 }'
需要更精确的控制输出的话,就要用printf
echo | awk '{ printf("%d %d %d",1,2,3) }'
echo | awk '{ printf("A=%0.3f B=%d C=%03d",1,2,3) }'
A=1.000 B=2 C=003
- 更多学习
Awk One-Liners one-liner awk scripts
Awk One-Liners Explained an explanation for the one-line awk scripts
Awk CheatSheet - a resource that lists all awk related variables
Gnu Awk Manual - a comprehensive, but fairly complex resource
一些命令

cat NC.gff | awk '{print $1,$2,$3}' | head -5
Chr1 TAIR10 chromosome
Chr1 TAIR10 gene
Chr1 TAIR10 mRNA
Chr1 TAIR10 protein
Chr1 TAIR10 exon
cat NC.gff | awk '{print $3,$5-$4+1}' | head -5
chromosome 30427671
gene 2269
mRNA 2269
protein 1871
exon 283
-
cat NC.gff | awk '$3 == "gene" {len=$5-$4+1;size+=len;print "Size:",size}'
计算所有基因的累计长度
一直累加,到最后一行是总和
Size: 61217607
Size: 61217680
Size: 61218118
Size: 61219702
Size: 61220038
Size: 61220156
Size: 61222091
Size: 61222409
Size: 61223024
-
cat TAIR10_GFF3_genes.gff |awk '$3 == "chromosome"{len=$5-$4 + 1; size += len; print "Size:", size } '
计算基因组长度(染色体累计长度) - 根据特征(features)把文件分开。
cat NC.gff | awk ' $3=="gene" { print $0 }' >> NC-genes.gff
cat NC.gff | awk ' $3=="CDS" { print $0 }' >> NC-cds.gff
- sam文件是tab分隔的,也可以用awk操作
上周的数据中,有多少碱基被覆盖了超过50次?
samtools depth ../lec16/results.bam | awk '$3 > 50 { print $0 } ' |wc -l
有多少的模板长度超过50 bp。
samtools view ../lec16/results.bam | awk ' $9 > 50 { print $0 } ' | wc -l
- 基因,基因名称和长度
cat NC.gff |awk '$3 == "gene"
{split($9, x, ";"); ## 第九列,按分号分割
split(x[1], y, "="); ##取第一列,并再次按等号分割
name = y[2];##取第二列
gsub(""", "", name); #不懂意思:用空格全局替换 " 符号,因为双引号是特殊字符,使用转义
print $3, name, $5 - $4 + 1 } '
gene ATMG01310 411
gene ATMG01320 5216
gene ATMG01330 384
gene ATMG01340 73
gene ATMG01350 438
gene ATMG01360 1584
gene ATMG01370 336
gene ATMG01380 118
gene ATMG01390 1935
gene ATMG01400 318
gene ATMG01410 615
- 提取需要的信息
- 初始将分隔符设定为制表符
- 如果是第一行,打印行名称
- 第3行开始,如果20列不是等号,且不以井号开始,打印多列
- 输出
awk 'BEGIN{OFS="\t";}
{if(FNR==1) print "target_name\taccession\tquery_name\tquery_start\tquery_end\tstrand\tscore\tEvalue";
if(FNR>2 && $20!="=" && $0!~/^#/)
print $2,$3,$4,$10,$11,$12,$17,$18; }'
my-genome.tblout >my-genome.tblout.final.xls