Linux学习与应用技巧

三剑客 | awk

2021-10-24  本文已影响0人  shwzhao

我刚开始一直不理解 awk 的语法,后来看师兄的代码,加上天天敲,有了点提高。

师兄在 2020-07-03 常用有趣命令之数据处理 中总结了很多代码,非常有用!
我经常记不住,用到时就会进去复制下来。下面是一些简单基础的用法。


1. 内置变量

$0: 记录变量,表示当前正在处理的记录,理解为整行
$n: 字段变量,其中n为整数,且 n 大于1,表示第 n 个字段的值,理解为第 n
NF: 当前记录的字段数(number of field),理解为列数
NR: 已经读入的记录数(number of record),理解为行数
FS: 字段分隔符(field seperator),默认列分隔符为空白,awk -F "," 即可设置为 ,
RS: 记录分隔符(record seperator);
OFS: 输出字段分隔符;
ORS: 输出记录分隔符;
FILENAM: 正在处理的数据文件的名称;
ARGIND: 实现多个文件的操作,可以参考:AWK实现多文件读取和处理awk打开多个文件的方法
FNR: 当前文档的记录数,多文件操作时使用。

awk '{$NF="";print}' a.txt

尤其是每行列数不一样时,尤为实用,但每行最后会多出一个分隔符,可以用函数gsub(/.$/,"")进行删除,也可以用管道 | sed 's/.$//'

awk '{if(FNR>1)print}' a.txt b.txt c.txt

2. 运算符

>g1
AGTCAT
CATACG
GCACTC
AT
>g2
CCATCA
TCAGGC
C
>g3
ACCTTG
GGCC
$ awk '/^>/&&NR>1{print "";}{ printf "%s",/^>/ ? $0" ":$0 }' gene.fa
>g1 AGTCATCATACGGCACTCAT
>g2 CCATCATCAGGCC
>g3 ACCTTGGGCC$

可发现每个基因变成了一行两列,第一列为id,第二列为序列。
加上| awk '{print $1"\n"}' 即可变成正常的单行 fasta 序列;
若加上| awk '{a+=length($2)}END{print a}' 即可得出序列的大小。

3. 函数

另外还有,字符串函数,index()match()split()sub();算术函数,int(x)sqrt(x)exp(x)...... 用不到,暂且留个印象。

$ echo "0.9774563" | awk '{print int($1*10000+0.5)*0.01"%"}'
97.75%

4. 数组

以下两行代码都是利用 数组 实现【转置】,代码是师姐网上找的,出处已经找不到了。

awk '{for(i=1;i<=NF;i++){if(NR==1)res[i]=$i;else res[i]=res[i]" "$i}}END{for(j=1;j<=NF;j++){print res[j]}}' a.txt
# 有几列就定义几个数组元素,运行每一行时对数组进行重新定义
awk '{for(i=1;i<=NF;i=i+1){a[NR,i]=$i}}END{for(j=1;j<=NF;j++){str=a[1,j];for(i=2;i<=NR;i++){str=str" "a[i,j]}print str}}' a.txt
# 先是对每一个值按坐标进行定义数组,按坐标把相同列的排成行,太慢了

Shell 的 join 命令可以联接多个文件,但需要进行排序,还总是会莫名报错,结果不可靠,awk 就很好使。

$ cat a.txt
gene2   noTF    others
gene1   TF      MYB
gene3   TF      HD-ZIP
gene15  noTF    others
$ cat b.txt
gene10  23      9
gene12  56      7
gene3   75      8
gene4   84      2
gene1   50      3
gene2   74      6
$ awk 'BEGIN{OFS="\t"}ARGIND==1{a[$1]=$0}ARGIND==2{if($1 in a)print a[$1],$2,$3; else print $1,"NA\tNA",$2,$3}' a.txt b.txt
gene10  NA      NA      23      9
gene12  NA      NA      56      7
gene3   TF      HD-ZIP  75      8
gene4   NA      NA      84      2
gene1   TF      MYB     50      3
gene2   noTF    others  74      6

5. 控制流

日常 | 2021-05-10 | 任意n个样本表达量超过0.5视为表达 的一个例子:

awk '{a=0;for(i=2;i<=NF;i++){if($i>0.5)a++};if(a>=2)print}' a.tsv
上一篇 下一篇

猜你喜欢

热点阅读