AWK
本文主要参考自https://www.tutorialspoint.com/awk/
AWK的工作流程
-
BEGIN语法在程序开始执行,仅执行一次,经常用它来初始化变量,AWK中的keywords都要求大写,该部分可选
BEGIN {awk-commands}
-
接下来是语法体部分,这个语法体将会每一行中我们指定的部分循环执行语句
/pattern/ {awk-commands}
-
最后是结束语句END,同样该部分为可选
END {awk-commands}
Ex: awk 'BEGIN{printf "Sr No\tName\tSub\tMarks\n"} {print}' marks.txt
可以使用-f
选项来指定awk脚本文件
Ex: awk -f command.awk marks.txt
可以使用-v
选项来为变量指定值,字符串要用""括起来,变量则不用
Ex:
awk -v name=Jerry 'BEGIN{printf "Name = %s\n", name}'
awk '{print $3 "\t" $4}' marks.txt
关于AWK中的pattern
awk程序可由一系列由pattern和对应的action组成的rule组成,不同的rule之间由;隔开,其中action一定由括号包裹,pattern一定无括号包裹。
- 正则表达式作pattern
Ex: awk '/555-5553/ { print $0 }' myfile
- 比较表达式作pattern
Ex:
awk '$NF == "A" { print $0 }' myfile
# 最后一个字段为A则输出
awk '$NF != "A" { print $0 }' myfile
# 最后一个字段不为A则输出
- 常量表达式作pattern
凡是非0的数字, 就表示pattern匹配成功, 也就是pattern为真. 否则表示匹配失败, 为假
凡是非空的字符串, 就表示pattern匹配成功, 也就是pattern为真. 否则表示匹配失败, 为假
注意: 字符串是由引号引起来的! 比如数字 0 与 字符串 “0” 不是一样的. 数字0为假, 字符串"0"为真(不为空)
Ex:
awk '0 { print $0 }' myfile
awk ' "0" { print $0 }' myfile
省略用法:
awk '{a=1};1' myfile
# 这里第一条rule省略了pattern,表示默认执行a=1,第二条rule的pattern为1,表示默认执行空commands即{print $0
},这里$0
表示所有内容
awk '1;1'
# 这里即每行打印两次
awk '/Amelia/ || /Martin/' myfile
awk '$NF ~ /F/' myfile
awk 'NR==5' myfile
BEGIN和END只是两个特殊的pattern
awk 'BEGIN { n=5 } NR==n { print $0 } END { print $0 }' myfile
awk 'length($0) > 18' marks.txt
模式范围
就像水龙头,在第一个匹配模式匹配成功时水龙头打开,执行语句体;接下来验证下一行是否匹配第二个匹配模式,若不匹配,仍然执行语句体,直到匹配第二个pattern为止,不执行语句体
awk '/start pos/,/end pos/ {print $0} myfile
awk '/start pos/,NR==XXX {print $0}' myfile
计数操作
awk 'BEGIN {c=0};/d/ {c++};END {print c}' scp.py
AWK的一些常用变量
ARGC
指的是参数个数
ARGV
指的是参数列表
awk 'BEGIN {
for (i = 0; i < ARGC - 1; ++i) {
printf "ARGV[%d] = %s\n", i, ARGV[i]
}
}' one two three four
得到
ARGV[0] = awk
ARGV[1] = one
ARGV[2] = two
ARGV[3] = three
ENVIRON
表示的是参数列表
awk 'BEGIN {print ENVIRON["USER"]}'
FILENAME
表示的是当前操作的文件名
awk 'END {print FILENAME}' marks.txt
NF
是number of fields的简称
head -n 1 file.txt | awk -F "\t" '{print NF}'
NR
是number of records的简称,表示到现在为止所读的行数
head -n 10 scp.py| awk -F " " '{print NR}'
FNR
对于多个文件可以分别从零计数行数
RLENGTH
指的是匹配字串的长度
awk 'BEGIN { if (match("One Two Three", "re")) { print RLENGTH } }'
AWK的正则表达
‘.’ It matches any single character except the end of line character.
awk '/[CT]all/'
awk '/[^CT]all/'
# 除了[]之外的
awk '/Call|Ball/'
awk '/Colou?r/'
# zero or one
awk '/cat*/'
# zero or more
awk '/2+/'
# one or more
awk '/Apple (Juice|Cake)/'
# matches the lines containing either Apple Juice or Apple Cake
AWK的数组
AWK的数组的索引可以是数字也可以是字符串,也不需要指定数组的长度
array_name[index] = value
delete array_name[index]
array["0,0"] = 100
if 语句
if (condition) action
if (condition) {actions}
if (condtion) action;else action
awk 'BEGIN {a=3;if (a%2==0) print "yes";else print "no"}'
if (condition) action;else if (condition) action
循环
awk 'BEGIN { for (i = 1; i <= 5; ++i) print i }'
awk 'BEGIN {i = 1; while (i < 6) { print i; ++i } }'
awk 'BEGIN {i = 1; do { print i; ++i } while (i < 6) }'
awk 'BEGIN {
sum = 0; for (i = 0; i < 20; ++i) {
sum += i; if (sum > 50) break; else print "Sum =", sum
}
}'
awk 'BEGIN {
for (i = 1; i <= 20; ++i) {
if (i % 2 == 0) print i ; else continue
}
}'
awk 'BEGIN {
sum = 0; for (i = 0; i < 20; ++i) {
sum += i; if (sum > 50) exit(10); else print "Sum =", sum
}
}'
退出执行
使用echo $?
来查看执行状况
实际使用的一些例子
awk -F"\t" '{print $1}'
zcat read1.fq.gz | awk '{if(NR%4==2) print}' | less -S
cat lambdaDNA.fa | awk -v RS="c" 'END {print --NR}'
cat train.txt | awk -F "\t" 'BEGIN {c=0} {if ($2=="0") c++} END {print c}'