工作原理
逐行读取文本,默认以空格或tab键为分隔符进行分隔,将分隔所得的各个字段保存到内建变量中,并按模式或者条件执行编辑命令
sed命令常用于一整行的处理,而awk倾向于将一行分成多个"字段"然后再进行处理
awk信息的读入也是逐行读取的,执行结果可以通过print的功能将字段数据打印显示
使用awk命令的过程中,可以使用逻辑操作符"&&"表示"与"、"|"表示"或"、"!"表示"非",还可以进行简单的数学运算,如+、-、*、/、%、^分别表示加、减、乘、除、取余和乘方
命令格式
awk 选项 '模式或条件 {操作}' 文件1 文件2 ……
awk -f 脚本文件 文件1 文件2
awk常见的内置变量(可直接使用):
| 内置变量 | 含义 |
|---|---|
| FS | 列分割符。指定每行文本的字段分隔符,默认为空格或制表位。与"-F"作用相同 |
| NF | 当前处理的行的字段个数 |
| NR | 当前处理的行的行号(序数) |
| $0 | 当前处理的行的整行内容 |
| $n | 当前处理行的第n个字段(第n列) |
| FILENAME | 被处理的文件名 |
| RS | 行分隔符。awk从文件中读取资料时,将根据RS的定义把资料切割成许多条记录, 而awk一次仅读入一条记录进行处理。预设值是"\n" |
注意:
$0 在shell主代码中代表的是脚本名
在函数体中代码的是函数名
在awk的命令代表的是当前整行内容
awk基础用法
按行输出内容
1.输出所有行内容
awk '{print}' test ##输出所有内容
awk '{print $0}' test
2.输出指定行内容
awk 'NR==1,NR==3{print $0}' test
awk '(NR>=4)&&(NR<=8) {print $0}' test
awk '(NR==4)||(NR==8) {print $0}' test
3.输出奇数行和偶数行
awk '(NR%2)==1 {print}' test ##奇数行
awk '(NR%2)==0 {print}' test ##偶数行
4.输出包含指定字符的行
awk '/^root/ {print $0}' /etc/passwd
awk '/bash$/ {print $0}' /etc/passwd
awk包含两种特殊的模式:BEGIN和END
两种模式的概念
BEGIN 模式指定了处理文本之前需要执行的操作:
END 模式指定了处理完所有行之后所需要执行的操作:
BEGIN模式表示,在处理指定的文本之前,需要先执行BEGIN模式中指定的动作; awk再处理指定的文本,之后再执行END模式中指定的动作,END{}语句块中, 往往会放入打印结果等语句
格式
awk 'BEDIN {操作1}; [条件] {操作2}; END {操作3};' 文件
BEDIN {操作1} awk在读取文件之前执行的操作
[条件] {操作2} awk逐行读取文件时执行的操作
END {操作3} awk在处理完文件所有行之后执行的操作
示例:
统计以nologin$结尾的行次数
awk 'BEGIN{a=0};/nologin$/ {a++}; END {print a}' pass
按字段输出内容
指定列分隔符的两种方式:使用-F 或 使用内建变量FS
使用 -F 指定分隔符
awk -F ':' '{print $1,$3}' /etc/passwd
将内建变量FS 重新赋值
awk 'BEGIN{FS=":"};{print $1,$3}' /etc/passwd
打印UID大于500的用户
awk -F ':' '$3>500 {print $1,$3}' /etc/passwd
打印UID小于等于500的用户(!取反)
awk -F: '!($3>500) {print $1,$3}' /etc/passwd
awk使用if语句
使用if语句时,内部条件要加( ),外面要加{ }
awk -F: '{if($3>500) {print $1,$3}}' /etc/passwd
awk三元运算符
Java和Shell中的三元运算符
java,C语言
- 条件表达式?值1:值2
- 当条件表达式为真时,取值1;当条件表达式为假时,取值2
shell
- [ 表达式 ] && 值1 || 值2
- 当表达式为真时,取值1;当表达式为假时,取值2
awk支持三元运算符,使用java的格式:
awk -F: '{max=($3>=$4)?$3:$4;{print max,$1}}' /etc/passwd
awk输出行号及内容
awk '{print NR,$0}' test
在指定分隔符下,输出包含指定内容的字段内容
$n~"xxx" ~代表的是指定字段包含某个字符串
$n=="xxx" ==代表的是指定字段为某个字段
$n!="xxx" !=代表的是指定字段不为某个字段
输出test文件中包含o字符的行内容
awk '$1~"o"{print NR,$0}' test
当第个7字段包含“bash"字符串时,打印该行的第1个字段和最后一个字段
awk -F: '$7~"bash" {print $1,$NF}' /etc/passwd
awk -F: '$NF~"bash" {print $1,$NF}' /etc/passwd
要求打印出第7个字段不等于"/bin/bash",且不等于"/sbin/nologin"的所有行
awk -F: '($7!="/bin/bash")&&($NF!="/sbin/nologin") {print}' /etc/passwd
awk的高级用法
RS 指定行分隔符
awk从文件中读取资料时,将根据RS的定义把资料切割成许多条记录, 而awk一次仅读入一条记录进行处理。内置变量RS的预设值是"\n"
通过管道处理其他命令的结果
统计行数
方法一:使用内置变量NR,打印最后一行行号
echo $PATH |awk 'BEGIN{RS=":"};{print NR,$0};END{print NR}
方法二:使用"wc -l" 统计行数
awk -F: '/bash$/{print}' pass | wc -l
统计内存使用率
free命令可以查看内存使用率,使用率=使用内存数量/总内存数量
int表示取整数
free | awk '/Mem:/ {print int($3/$2*100)"%"}'
或
free | awk '/Mem:/ {print $3/$2*100}' | awk -F. '{print $1"%"}'
过滤出CPU的空闲率
top 查看CPU使用情况
top -b -n 1 只会输出一次top结果 不会在次刷新
top -b -n 1 |awk -F, '/Cpu/{print $4}' |awk '{print int($1)"%"}'
显示上次系统重启时间
1./proc/uptime 解析
[root@localhost demo]#cat /proc/uptime
28923.34 57775.79
第一列输出的是,系统启动到现在的时间(以秒为单位),这里简记为a 第二列输出的是,系统空闲的时间(以秒为单位),这里简记为b
系统的空闲率(%)=b/(a*N) N是系统中CPU的数量
2.uptime
[root@localhost demo]#uptime
19:11:05 up 8:01, 1 user, load average: 0.00, 0.01, 0.05
| 说明 | |
|---|---|
| 19:11:05 up | 系统当前时间 |
| 8:01 | 系统已经运行了多长时间 |
| 1 use | 目前有多少登陆用户 |
| load average: 0.00, 0.01, 0.05 | 系统在过去的1分钟 5分钟 15分钟内的平均负载 |
3.命令
date -d "$(awk -F '.' '{print $1}' /proc/uptime)second ago" +"%F %H:%M:%S"
getline命令详解
获取当前行 光标移到下一行
seq 10 | awk '{getline; print $0}'
getline 如果左右无 | 或 < ,是 awk 先读取文件首行内容,然后再由getline读取行内容并移动到下一行
seq(squeue) 是一个序列的缩写,主要用来输出序列化的东西
用法: seq[选项]... 尾数
seq[选项]... 首数 尾数
seq[选项]... 首数 增量 尾数
以指定增量从首数开始打印数字到尾数
awk 'BEGIN {"hostname" | getline; print $0}' #调用 hostname,并输出当前的主机名
getline 如果左右有 | 或 < ,getline 用于直接获取内容,此时 $0 的值为 getline 获取的内容
调用w命令,并用来统计在线用户数
awk 'BEGIN {n=0 ; while ("w" | getline) n++ ; print n-2}' #调用w命令,并用来统计在线用户数
注:getline是按照行读取内容,因为前面有管道符号,所以读取一行为1 读取两行为2 输出n-2是为了减去前两行的汇总
OFS详解
OFS表示输出时可设置改变分隔符
[root@localhost ~]#echo 'A B C D' | awk '{print $1,$3}'
A C
[root@localhost ~]#echo 'A B C D' | awk 'BEGIN{OFS=":"};{print $1,$3}'
A:C
[root@localhost ~]#echo 'A B C D' | awk 'BEGIN{OFS=":"};{print $0}'
A B C D
[root@localhost ~]#echo 'A B C D' | awk 'BEGIN{OFS=":"};{$1=$1;print $0}'
A:B:C:D
[root@localhost ~]#echo 'A B C D' | awk '{OFS=":";$1=$1;print $0}'
A:B:C:D
$1=$1 是用来激活$0的重新赋值,也就是说
字段$1...和字段数NF的改变会促使awk重新计算$0的值,通常是在改变OFS后而需要输出$0时这样做
使用awk结合for循环遍历创建数组
[root@localhost ~]#awk 'BEGIN {a[0]=10;a[1]=20;print a[1]}'
20
[root@localhost ~]#awk 'BEGIN {a["ab"]="aaa";a["bc"]="bbb";print a["ab"]}'
aaa
[root@localhost ~]# awk 'BEGIN{a[0]=10;a[1]=20; for(i in a){print i,a[i]}}'
0 10
1 20
使用awk结合for循环以及sort统计重复的次数并排序
awk '{a[$1]++} END{for(i in a){print a[i],i}}' test.txt | sort -rn
解析:
{a[$1]++} awk 根据指定字段读取每行的字段内容,使用字段内容作为数组的下标,如果出现相同内容的行,则用这个行内容做的数组的值自增1
END{for(i in a){print a[i],i}} awk 读取完所有行内容后,使用for循环遍历这个数组的下标,打印每个下标出现的次数和下标的值