awk 入门与进阶 part1—快速入门
awk 的结构
由一个单独的模式–动作语句(pattern-action statement) 组成。
pattern{ action }
awk的运行方式
awk 的基本操作是在由输入行组成的序列中,陆续地扫描每一行,搜索可以被模式匹配(match) 的行。每一个输入行轮流被每一个模式测试。每匹配一个模式,对应的动作(可能包含多个步骤) 就会执行。然后下一行被读取,匹配重新开始。这个过程会一起持续到所有的输入被读取完毕为止。
执行awk方式
- awk+执行语句+文件
awk 'program' input files
- awk+执行语句
在命令行上省略输入文件,在这种情况下, awk会将program应用到接下来在终端输入的内容,直到键入文件结束标志ctrl-d。
- awk+脚本
awk -f progfile optional list of files
入门应知
输出
awk 从输入中每次读取一行,将行分解为一个个的字段(默认将字段看作是非空白字符组成的序列)。当前输入行的第一个字段叫作$1,第二个是$2,依次类推。一整行记为$0。每行的字段数有可能不同。
print 打印当前输出行,$0 表示整行,$1 表示第一个字段。在print 语句中由逗号分隔的表达式, 在输出时默认用一个空格符分隔。Awk 计算当前输入行的字段数量,并将它存储在一个内建的变量中,这个变量叫作NF。$NF表示打印最后一个字段。
用字段的值进行计算,并将计算得到的结果放在输出语句中。如{print $1*$2}
。
另一个内建变量NR,这个变量计算到目前为止,读取到的行的数量。我们可以使用NR来表示行号。添加行号写法{ print NR, $0 }
。添加文本,引号包围的文本会和字段和运算结果一起输出。
修改输出格式可以试用printif。使用格式printf(format, value1, value2, ..。, valuen)
format 是一个字符串,包含按字面打印的文本, 中间包括格式说明符, 格式说明符用于说明如何打印值。一个格式说明符是一个%,后面跟着几个字符控制一个value 的输出格式。第一个格式说明符说明value1 的输出格式,第二个格式说明符说明value2 的输出格式,依次类推。使用printf 不会自动产生空格符或换行符必须自己添加\n。
选择
通过比较和计算或者文本可以选择输出感兴趣的行。
$1 >= 5
$1+$3 > 10
$1=="chr1"
结合逻辑运算符进行组合选择。
|| or; && and; ! not
数据验证
真实的数据总是存在错误,检查数据是否具有合理的值,格式是否正确,通常称作数据验证(data validation),数据验证的本质是否定,也就是说打印出可以的行。比如想验证是不是每一行都有4列,即可以使用NF != 4 {print $0}
BEGIN END
特殊的模式BEGIN 在第一个输入文件的第一行之前被匹配,END 在最后一个输入文件的最后一行被处理之后匹配。
计算
#计数:
awk '$2>1{num=num +1}END{print num}' awk.txt
#总数
awk 'END{print NR}' awk.txt
#平均数
awk '{sum=sum + $2}END{print sum/NR}' awk.txt
# 输出最大值(变量可以是字符串)
awk '$2 > max { max = $2; maxid = $1 }END { print max, maxid }' awk.txt
# 字符串拼接
awk '{id = id $1 " " }END { print id }' awk.txt
#字符个数 length
awk '{ print $3,length($3) }' awk.txt
流程控制
if-else
awk '
{ n = $2; id =$1 }
END { if (n > 333)
print n,id
else print "< 333"
}' awk.txt
for:大多数循环都包括初始化, 测试, 增值, 而for 语句将这三者压缩成一行。
awk '
{ for(i=1;i<= NR; i=i+1)
print i,$2' awk.txt
while:while 含有一个条件判断与一个循环体. 当条件为真时, 循环体执行.
awk '{ i = 1
while (i <= NR) {
print i, $1
i = i + 1
}
}' awk.txt
while 后面被括号包围起来的表达式是条件判断;循环体是跟在条件判断后面的,被花括号包围起来的的两条语句。
数组
Awk 提供了数组用来存储一组相关的值。
#逆序显示
awk'{ line[NR] = $0 } # remember each input line
END { i = NR # print lines in reverse order
while (i > 0) {
print line[i]
i = i - 1
}
}' awk.txt
awk'
{ line[NR] = $0 } # remember each input line
END { for (i = NR; i > 0; i = i - 1)
print line[i]
}'
awk常用一行命令
#1. 输入行的总行数
END { print NR }
#2. 打印第10 行
NR == 10
#3. 打印每一个输入行的最后一个字段
{ print $NF }
#4. 打印最后一行的最后一个字段
{ field = $NF }
END { print field }
#5. 打印字段数多于4 个的输入行
NF > 4
#6. 打印最后一个字段值大于4 的输入行
$NF > 4
#7. 打印所有输入行的字段数的总和
{ nf = nf + NF }
END { print nf }
#8. 打印包含Beth 的行的数量
/Beth/ { nlines = nlines + 1 }
END { print nlines }
#9. 打印具有最大值的第一个字段, 以及包含它的行(假设$1 总是正的)
$1 > max { max = $1; maxline = $0 }
END { print max, maxline }
#10. 打印至少包含一个字段的行
NF > 0
#11. 打印长度超过80 个字符的行
length($0) > 80
#12. 在每一行的前面加上它的字段数
{ print NF, $0 }
#13. 打印每一行的第1 与第2 个字段, 但顺序相反
{ print $2, $1 }
#14. 交换每一行的第1 与第2 个字段, 并打印该行
{ temp = $1; $1 = $2; $2 = temp; print }
#15. 将每一行的第一个字段用行号代替
{ $1 = NR; print }
#16. 打印删除了第2 个字段后的行
{ $2 = ""; print }
#17. 将每一行的字段按逆序打印
{ for (i = NF; i > 0; i = i - 1) printf("%s ", $i)
printf("\n")
}
#18. 打印每一行的所有字段值之和D
{ sum = 0
for (i = 1; i <= NF; i = i + 1) sum = sum + $i
print sum
}
#19. 将所有行的所有字段值累加起来
{ for (i = 1; i <= NF; i = i + 1) sum = sum + $i }
END { print sum }
#20. 将每一行的每一个字段用它的绝对值替换
{ for (i = 1; i <= NF; i = i + 1) if ($i < 0) $i = -$i
print
}