Awk 是一个强大的文本分析工具,它每次读入一条记录,并把每条记录切分成字段后进行分析。Awk 官方文档是非常好的学习材料,通过man awk
查看。
awk 'BEGIN { action } pattern { action } END { action }'
Awk 程序通常是一系列 pattern {action}对:
pattern
,表示模式匹配,只处理匹配的行。pattern 可以省略,表示匹配所有行
action
,表示对匹配行所做的动作。{actions}可以省略,表示{ print }。BEGIN
和END
的{action}不能省略
pattern 可能是:
BEGIN
, 执行初始化操作,程序开始时执行一次
END
,执行收尾工作,程序结束时执行一次
expression
,一个表达式,既可以是判断语句,也可以是正则表达式
常用参数
-F value
设置域分隔符,相当于给 FS 内置变量赋值-v var=value
将变量 value 的值赋给程序变量 var,-v 可以多次使用
记录与字段
记录是一次读入的内容,通常是文件的一行,保存在字段变量
1,
NF 中。
表达式与操作符
Awk 表达式的符号与 C 语言的类似,基本的表达式有数字,字符串,变量,字段,数组以及函数调用。变量无需声明,它们在首次使用时被初始化为null
。
assignment = = -= *= /= %= ^=
conditional ? :
logical and &&
logical or ||
logical not !
array membership in
matching ~ !~
relational < > <= >= == !=
concatenation (no explicit operator)
add ops -
mul ops * / %
unary -
exponentiation ^
inc and dec -- (both post and pre)
field $
正则表达式
在 Awk 中语言中,通常测试一个记录、字段或字符串是否与一个正则表达式匹配,匹配返回 1,不匹配返回 0。正则表达式用两个反斜杠/
包围。
expr ~ /r/ # 评估expr是否与r匹配。匹配的意思是expr的一个子串是否在正则表达式r定义的字符串集中。
/r/ { action }, $0 ~ /r/ { action } # 两者相同, /r/ 等于 $0 ~ /r/
任何表达式都可以放到~
和!~
右边或者内建的需要正则表达式的地方。在必要的时候,该表达式会被转变成字符串,然后作为一个正则表达式来解释。以下三行 awk 命令完成同样的功能:输出第 5 列为 10 的的行。
seq 20 | xargs -n5 > file
# cat file
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
awk '$5 ~ /10/' file
awk '$5 ~ "10"' file
awk '$5 ~ 10' file
数组
Awk 支持一维数组。其表示方法为array[expr]
,expr
在内部被统一转换成字符串类型,因此 A[1],与 A["1"]相同,事实上索引都是“1”。索引为字符串的数组被称为关联数组。expr in array
用于判断数组元素 array[expr]是否存在。
for ( var in array ) statement
控制语句
代码语言:javascript复制if ( expr ) statement
if ( expr ) statement else statement
while ( expr ) statement
do statement while ( expr )
for ( opt_expr ; opt_expr ; opt_expr ) statement
for ( var in array ) statement
continue
break
内置变量
NR
- 当前行数NF
- 当前行的列数RS
,行分隔符,默认是换行符FS
,列分隔符,默认是空格和制表符ORS
,输出行分隔符,默认为换行符OFS
,输出列分隔符,默认为空格FILENAME
,当前文件名
内置函数
字符串函数
sub()、substr()、gsub(),sprintf(),index(),length(), match(),split(),tolower(), toupper()
数学函数
sin(),cos(), ...
输入输出
有两个输出语句,print
和printf
print# 打印整条记录到标准输出,相当于print $0
print expr1, expr2, ..., exprn # 打印指定字段到标准输出
printf format, expr-list # C语言printf函数的重用
输入函数 getline 有以下几种形式:
代码语言:javascript复制getline # 读取下一条记录到 $0,更新NF,NR和FNR
getline var # 读取下一条记录到var,更新NR和FNR
getline < file # 从文件读取记录到 $0,更新NF
getline var < file # 从文件读取记录到var
command | getline # 通过管道传递command的结果到 $0,更新NF
command | getline var # 通过管道传递command的结果到var
代码语言:javascript复制seq 10 | awk '{print $0;getline}'# 显示奇数行
seq 10 | awk '{getline; print $0}'# 显示偶数行
seq 10 | awk '{getline tmp; print tmp; print $0}'# 奇偶行对调
awk 'BEGIN {"date" | getline;close("date");print $0}'# 得到系统当前时间
# fastq转换成fasta
awk '{getline seq; getline comment; getline quality; sub("@", ">", $0); print $0"n"seq}' file
示例
代码语言:javascript复制awk '{print $0}' file # 打印整行
awk '{print $1}' file # 打印第一列
awk '{print $2}' file # 打印第二列
awk '{print $NF}' file # 打印最后一列
awk '{print $(NF-1)}' file#打印倒数第二列
awk -F ';' -v OFS='t''{print $1,$2,$NF}' file # 读入的文件以逗号;分隔列,打印第1列,第2列和最后一列,并且打印时以制表符作为列的分隔符
number=10;awk -v n=$number'{print n}' file # number的值被传给了程序变量n
awk '$2 > 100' file # 打印第2列大于100的行
awk 'NR>1 && NR<4' file # 打印第2~3行
awk '/EGFR/' file # 打印含有EGFR的行,相当于grep EGFR file
awk '$1 ~ /EGFR/' file # 打印第1列含有EGFR的列
# 按指定列去除重复行
# cat file
1 2 3 4 5
6 2 8 9 10
11 12 13 14 15
16 17 18 19 20
awk '!a[$2] ' file # 第二列出现两次2,只保留第一次出现的那一行,结果如下:
1 2 3 4 5
11 12 13 14 15
16 17 18 19 20
awk '{sum =$1} END {print sum}' file # 累加文件的第一列
awk '{sum =$1} END {print sum/NR}' file # 求第一列的平均数
# 从含有多条fasta序列的文件中提取指定序列
awk -v RS=">"'/chr1/ {print $0}' hg19.fa # 提取chr1的序列
awk -v RS=">"'/chr1|chr2/ {print $0}' hg19.fa # 提取chr1和chr2的序列