awk备忘录

入门

awk的基本命令格式 awk 'pattern{action}',省略action时,默认action是{print},如awk '1'就是awk '1{print}'

介绍

  1. 和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
  1. awk如何工作
    awk 'CONDITION { ACTIONS }'
    awk 'CONDITION1 { ACTIONS1 } CONDITION2 { ACTIONS2 } CONDITION3 { ACTIONS3 }'
    比如,我们可以设定一个条件,输入的第5列要小于40,就打印
    samtools view demo.bam | awk '$5 < 60 { print $5 }' | head

  2. awk可能出现的问题
    大部分空格都可以识别,因为当制表符分隔的文件某一列为空时,会错位。因此最好每次都定义制表符分隔,或设置到bashrc中。
    awk -F '\t'
    alias awk="awk -F '\t'"

  3. 一些特定符号
    $0 原始的整行
    NF number of columns
    NR line number
    OFS output fields separator
    FNR file line number(如果在两个文档上运行,line number会在第二个文件的时候reset到1再开始)

最后一列 $NF

  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还是仅仅只用来选择满足条件的行最好。

  2. 复杂的条件
    > or <: '$1 < 60 { print 41 }'
    ==, != :'{ $1 == "ORF" { print $1 }'
    ~, !~ 匹配或不匹配(正则表达式): ' $1 ~ "YALC|YALW" { print $1 }'
    匹配 pattern另一种方法是将pattern用/包围, 称为regexp constant: ' $1 ~ /YALC|YALW/ { print $1 }'

  3. 输出格式
    修改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

  1. 更多学习
    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

一些命令

awk备忘录_第1张图片
屏幕快照 2017-10-30 上午10.12.36.png
  1. 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

  1. cat NC.gff | awk '{print $3,$5-$4+1}' | head -5

chromosome 30427671
gene 2269
mRNA 2269
protein 1871
exon 283

  1. 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

  1. cat TAIR10_GFF3_genes.gff |awk '$3 == "chromosome"{len=$5-$4 + 1; size += len; print "Size:", size } '
    计算基因组长度(染色体累计长度)
  2. 根据特征(features)把文件分开。
    cat NC.gff | awk ' $3=="gene" { print $0 }' >> NC-genes.gff
    cat NC.gff | awk ' $3=="CDS" { print $0 }' >> NC-cds.gff
  3. 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
  4. 基因,基因名称和长度
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

  1. 提取需要的信息
  • 初始将分隔符设定为制表符
  • 如果是第一行,打印行名称
  • 第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 && 0!~/^#/)
print 3,10,12,18; }'
my-genome.tblout >my-genome.tblout.final.xls

  1. 去重复
    对于awk '!a[$3]++',需要了解3个知识点
  • awk数组知识
  • awk的基本命令格式 awk 'pattern{action}',省略action时,默认action是{print},如awk '1'就是awk '1{print}'
  • var++的形式:先读取var变量值,再对var值+1

以数据

1 2 3
1 2 3
1 2 4
1 2 5

为例,对于 awk '!a[$3]++'

  • awk 处理第一行时: 先读取a[$3]的值再自增,a[$3]a[3]值为空(0),即为awk '!0',即awk '1',即awk '1{print}'
  • awk 处理第二行时: 先读取a[$3]值再自增,a[$3]a[3]值为1,即为awk '!1',即awk '0',即awk '0{print}'
  1. ls | awk -F "." '{print $1}'|xargs -I '{}' mv ./{}.sh ./{}.txt

匹配sh后缀,替换成txt

  1. awk 'NR>=31&&NR<=35'

  2. awk -F " " '{$1="";print $0}'
    去除第一列,输出第二列到最后一列

你可能感兴趣的:(awk备忘录)