我刚开始一直不理解
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. 函数
- 字符串函数
length()
: 返回字符串的长度
gsub()
: 替换所有出现的子串
substr()
: 截取指定长度的子串。
另外还有,字符串函数,
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
网友评论