awk
工作原理
逐行读取文本,默认以空格或tab键为分隔符进行分隔,将分隔所得的各个字段保存到内建变量中,并按模式或者条件执行编辑命令。
内建变量:是awk预定义好的,内置在awk内部的变量,可理解为awk的内部变量。
sed命令常用于一整行的处理,而awk比较倾向于将一行分成多个"字段"然后再进行处理。
awk信息的读入也是逐行读取的,执行结果可以通过print的功能将字段数据打印显示。
在使用awk命令的过程中,可以使用逻辑操作符" &&"表示"与"、"||"表示"或”、"!"表示"非";还可以进行简单的数学运算,如+、-、*、/、%、^分别表示加、减、乘、除、取余和乘方。
命令格式
awk 选项 '模式或条件 {操作}' 文件1 文件 2 ...
awk -f 脚本文件 文件1 文件2 ...
awk常见的内建变量(可直接用)
| 内建变量 | 作用 |
|---|---|
| FS | 列分割符。指定每行文本的字段分隔符,默认为空格或制表位。与"-r"作用相同 |
| NF | 当前处理的行的字段个数 |
| NR | 当前处理的行的行号(序数) |
| $0 | 当前处理的行的整行内容 |
| 在shell主代码中代表的是脚本名 | |
| 在函数体中代码的是函数名 | |
| $n | 当前处理行的第n个字段(第n列) |
| FILENAME | 被处理的文件名 |
| RS | 行分隔符。awk从文件上读取资料时,将根据RS的定义把资料切割成许多条记录,而awk一次仅读入一条记录,以进行处理。预设值是'\n' |
按行输出文本
-
输出所有行内容
注:awk不能识别双引号下的$
-
输出指定范围行
-
也可以使用大于等于或小于等于
-
也可以使用||(或)符号
-
输出奇数行、偶数行
-
-
根据内容匹配行
- 使用正则匹配
- 使用正则匹配
模式的使用
awk 'BEGIN {操作1}; 条件 {操作2}; END {操作3}' 文件名
- BEGIN {操作1}:awk在读取文件之前执行的操作
- [条件] {操作2}:awk逐行读取文件时执行的操作
- END {操作3}:awk 在处理完文件所有行之后执行的操作
例: 统计指定结尾的行数。
-
grep -c实现
-
awk通过模式实现
BEGIN模式表示,在处理指定的文本之前,需要先执行BEGIN模式中指定的动作;
awk再处理指定的文本,之后再执行END模式中指定的动作,END语句块中,往往会放入打印结果等语句。
按字段查找内容
查找指定行,等通过位置变量获取
例:输出passwd下所有用户名和uid
此外,还可以加入条件进行筛选。
-
uid大于500
-
uid小于10
-
加入三元运算符
例:如果uid大于gid,输出uid,反之输出gid
输出行号
通过sed输出行号,行号和内容不在同一行。
通过awk输出,行号在内容前。
包含字符
- $n~"XXX":~代表的是指定字段包含某个字符串\
- $n=="XXX":==代表的是指定字段为某个字符串\
- $n !="XXX":!=代表的是指定字段不为某个字符串
如果不知道字段总共多长,可使用$NF表示最后一个字段
使用NR统计字段数
RS的作用为记录分隔符,且默认值为换行。
统计行数
可通过管道符交给wc -l处理
结果导入到文件
-
外侧重定向输出
-
内部重定向输出
实例一:将已使用内存以百分比的形式输出
free | awk '/Mem:/ {print int($3/$2*100)"%"}'
实例二:输出CPU空闲率
top -bn1 | awk -F , '/Cpu/ {print $4}' | awk '{print $1"%"}'
实例三:输出上次启动时间
date -d "$(awk '{print $1}' /proc/uptime) second ago" +"%Y/%m/%d %H:%M:%S"
- /proc/uptime2个数字的意义,第一个数值代表系统总的启动时间,第二个数值则代表系统空闲的时间,都是用秒来表示的。
扩展
getline
获取当前行内容,并将光标移动到下一行(与sed中n操作相似)
- getline如果左右无│或<,是 awk 先读取文件首行内容,然后再由getline读取行内容并移动到下一行
awk 'BEGIN {"hostname" | getline; {print $0}}'
- getline如果左右有|或<,getline用于直接获取内容,此时$o的值为getline获取的内容
awk 'BEGIN{n=0; while("w" | getline) n++; print n-2}'
OFS:输出后结果分隔符修改
awk 'BEGIN{OFS="分隔符"}; {print 参数}'
awk '{OFS="分隔符"; print $1,$3}'
但是$0整行输出时无法直接改变分隔符
用$0输出,并且要求自己定的分隔符,需要激活一下,激活$0重新赋值
awk的数组
下标也可以由字符串表示
赋予的值也可以为字符串
循环遍历输出数组
awk读取完所有行内容后,使用for循环遍历这个数组的下标,打印每个下标出现的次数和下标的值
统计元素重复次数
-
通过sort排序,uniq -c统计次数
-
awk根据指定字段读取每行的字段内容,使用字段内容作为数组的下标,如果出现相同内容的行,则用这个行内容做的数组的值自增一
优化后:
数组元素去重
-
awk ‘1’就是awk '1{print}',允许打印读入的行内容,例:echo 123 | awk '1'
-
awk '0’就是awk '0{print}',不允许打印读入的行内容,例:echo 123 | awk '0'
-
awk处理第一行时:先读取a[$1]值再自增,a[$1]即 a[1]值为空(即0),即为 awk '!0',即为 awk '1',即为 awk'1{print}'
-
awk处理第二行时:先读取 a[$1]值再自增,a[$1]即 a[1]值为1,即为 awk '!1',即为 awk '0',即为 awk ‘0{print}'