文本三剑客之一——awk

236 阅读3分钟

image.png


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'

按行输出文本

  • 输出所有行内容 image.png

    :awk不能识别双引号下的$ image.png image.png

  • 输出指定范围行 image.png

    • 也可以使用大于等于或小于等于 image.png

    • 也可以使用||(或)符号 image.png

    • 输出奇数行、偶数行 image.png

  • 根据内容匹配行 image.png

    • 使用正则匹配 image.png

模式的使用

awk 'BEGIN {操作1}; 条件 {操作2}; END {操作3}' 文件名
  • BEGIN {操作1}:awk在读取文件之前执行的操作
  • [条件] {操作2}:awk逐行读取文件时执行的操作
  • END {操作3}:awk 在处理完文件所有行之后执行的操作

: 统计指定结尾的行数。

  • grep -c实现 image.png

  • awk通过模式实现 image.png

BEGIN模式表示,在处理指定的文本之前,需要先执行BEGIN模式中指定的动作;
awk再处理指定的文本,之后再执行END模式中指定的动作,END语句块中,往往会放入打印结果等语句。

按字段查找内容

查找指定行,等通过位置变量获取 image.png

:输出passwd下所有用户名和uid image.png image.png

此外,还可以加入条件进行筛选。

  • uid大于500 image.png image.png image.png

  • uid小于10 image.png

  • 加入三元运算符
    例:如果uid大于gid,输出uid,反之输出gid image.png

输出行号

通过sed输出行号,行号和内容不在同一行。 image.png

通过awk输出,行号在内容前。 image.png

包含字符
  • $n~"XXX":~代表的是指定字段包含某个字符串\
  • $n=="XXX":==代表的是指定字段为某个字符串\
  • $n !="XXX":!=代表的是指定字段不为某个字符串

image.png image.png

如果不知道字段总共多长,可使用$NF表示最后一个字段 image.png

使用NR统计字段数

RS的作用为记录分隔符,且默认值为换行。 image.png

统计行数

可通过管道符交给wc -l处理 image.png

结果导入到文件
  • 外侧重定向输出 image.png

  • 内部重定向输出 image.png

实例一:将已使用内存以百分比的形式输出

free | awk '/Mem:/ {print int($3/$2*100)"%"}'

image.png

实例二:输出CPU空闲率

top -bn1 | awk -F , '/Cpu/ {print $4}' | awk '{print $1"%"}'

image.png

实例三:输出上次启动时间

date -d "$(awk '{print $1}' /proc/uptime) second ago" +"%Y/%m/%d %H:%M:%S"
  • /proc/uptime2个数字的意义,第一个数值代表系统总的启动时间,第二个数值则代表系统空闲的时间,都是用秒来表示的。 image.png

image.png

扩展

getline

获取当前行内容,并将光标移动到下一行(与sed中n操作相似) image.png

  • getline如果左右无│或<,是 awk 先读取文件首行内容,然后再由getline读取行内容并移动到下一行
awk 'BEGIN {"hostname" | getline; {print $0}}'

image.png

  • getline如果左右有|或<,getline用于直接获取内容,此时$o的值为getline获取的内容
awk 'BEGIN{n=0; while("w" | getline) n++; print n-2}'

image.png

OFS:输出后结果分隔符修改

awk 'BEGIN{OFS="分隔符"}; {print 参数}'
awk '{OFS="分隔符"; print $1,$3}'

image.png image.png

但是$0整行输出时无法直接改变分隔符 image.png

用$0输出,并且要求自己定的分隔符,需要激活一下,激活$0重新赋值 image.png

awk的数组

image.png

下标也可以由字符串表示 image.png

赋予的值也可以为字符串 image.png

循环遍历输出数组

awk读取完所有行内容后,使用for循环遍历这个数组的下标,打印每个下标出现的次数和下标的值 image.png

统计元素重复次数
  • 通过sort排序,uniq -c统计次数 image.png

  • awk根据指定字段读取每行的字段内容,使用字段内容作为数组的下标,如果出现相同内容的行,则用这个行内容做的数组的值自增一 image.png image.png

    优化后image.png image.png

数组元素去重
  • awk ‘1’就是awk '1{print}',允许打印读入的行内容,例:echo 123 | awk '1'

  • awk '0’就是awk '0{print}',不允许打印读入的行内容,例:echo 123 | awk '0' image.png

  • 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}' image.png