Shell系统编程三剑客之----AWK

目录

一:AWK介绍

1.AWK工具简介

2.AWK的基本格式

3.AWK工作原理

4.常见的内建变量(可直接用)

二: AWK实例

1.按行输出文本

2.按字段输出文本

 3.通过管道、双引号调用 Shell 命令

 4.date命令输出时间

5. 查看内存使用占比

6.查看cpu使用占比

7.获取奇数偶数行

​ 8.OFS 输出分割符

 9.数组

10.查重

 11.过滤密码失败


一:AWK介绍

1.AWK工具简介

●AWK 是一种处理文本文件的语言,它是一个强大的文本分析工具,它是专门为文本处理设计的编程语言,也是行处理软件,通常用于扫描、过滤、统计汇总工作。

●可以在无交互的模式下实现复杂的文本操作;数据可以来自标准输入也可以是管道或文件

●相较于sed常作用于一整个行的处理,awk则比较倾向于一行当中分成数个字段来处理,因为awk相当适合小型的文本数据。

2.AWK的基本格式

1.awk [选项] ‘模式条件{操作}’ 文件1 文件2…
2.awk -f 脚本文件 文件1 文件2…
格式:awk关键字 选项 命令部分 ‘{xxx}’ 文件名

3.AWK工作原理

● 前面提到sed命令常用于一整行的处理,而awk比较倾向于将一行分成多个"字段"然后再进行处理,且默认情况下字段的分隔符为空格或tab键。awk 执行结果可以通过print的功能将字段数据打印显示。

●在使用awk命令的过程中,可以使用逻辑操作符"&&“表示"与”、"||“表示"或”、"!“表示"非”;还可以进行简单的数学运算,如+、-、*、/、%、^分别表示加、减、乘、除、取余和乘方。

●awk后面接两个单引号并加上大括号{ }来设置想要对数据进行的处理操作,awk可以处理后续接的文件,也可以读取来自前个命令的标准输。

4.常见的内建变量(可直接用)

变量 含义
FS 列分割符。指定每行文本的字段分隔符,默认为空格或制表位。与"-F"作用相同
NF 当前处理的行的字段个数
NR 当前处理的行的行号(序数)
$0 当前处理的行的整行内容
$1 代表第一列的内容
$2 代表第二列的内容
$n 当前处理行的第n个字段
FILENAME 被处理的文件名。
RS 行分隔符

注:awk从文件上读取资料时,将根据RS的定义把资料切割成许多条记录,而awk一次仅读入一条记录,以进行处理。预设值是’\n’
简说:数据记录分隔,默认为\n,即每行为一条记录。

二: AWK实例

1.按行输出文本

#输出所有内容
[root@localhost ~]# awk '{print}' a
[root@localhost ~]# awk '{print $0}' a

#输出1-3行的内容
[root@localhost ~]# awk 'NR==1,NR==3{print}' a
[root@localhost ~]# awk '(NR>=1)&&(NR<=3){print}' a

#输出第一行或第三行
[root@localhost ~]# awk 'NR==1||NR==3{print}' a

#输出4-8行,或10行
[root@localhost ~]# awk '(NR>=4&&NR<=8)||NR==10 {print $0}' a
four
five
six
seven
eight
ten

[root@localhost ~]# awk '(NR%2)==1{print}' a    #输出所有奇数行
[root@localhost ~]# awk '(NR%2)==0{print}' a    #输出所有偶数行

#配合正则表达式使用输出
[root@localhost ~]# awk '/^root/{print}' /etc/passwd        #输出以root开头的行
[root@localhost ~]# awk '/nologin$/{print}' /etc/passwd     #输出以 nologin 结尾的行
[root@localhost ~]# awk 'NR!=10 {print $0}' a               #输出不是第10行的所有行

#统计以nologin为结尾的行数
[root@localhost ~]# grep -c "nologin$" /etc/passwd
[root@localhost ~]# awk '/nologin$/ {print $0}' /etc/passwd | wc -l
[root@localhost ~]# awk 'BEGIN {x=0}; /nologin$/ {x++}; END {print x}' /etc/passwd
[root@localhost ~]# awk 'BEGIN {x=0}; /nologin$/ {x++; print x, $0}; END {print x}' /etc/passwd

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

2.按字段输出文本

#输出以root开头的行的第一部分
[root@localhost ~]# awk -F: '/^root/ {print $1}' /etc/passwd

#输出以root开头的行的第一部分和第三部分
[root@localhost ~]# awk -F: '/^root/ {print $1,$3}' /etc/passwd

#输出以root开头的行的第一部分和第三部分,最后一部分
[root@localhost ~]# awk -F: '/^root/ {print $1,$3,$NF}' /etc/passwd

#输出第三部分不小于200的行
[root@localhost ~]# awk -F ":" '!($3<200){print}' /etc/passwd 

#以冒号为分隔符,第三部分大于等于1000。先处理完BEGIN的内容,再打印文本里面的内容
[root@localhost ~]# awk 'BEGIN {FS=":"};{if($3>=1000){print}}' /etc/passwd

#!表示为取反
[root@localhost ~]# awk -F: '!($3>8) {print $3,$1}' /etc/passwd
[root@localhost ~]# awk -F: 'BENGIN {FS=":"}; !($3>8) {print $3,$1}' /etc/passwd

#($3>$4)?$3:$4;三元运算符,如果第3个字段的值大于等于第4个字段的值,则把第3个字段的值赋给max,否则第4个字段的值赋给max
[root@localhost ~]# awk 'BEGIN {FS=":"};{if($3>=1000){print}}' /etc/passwd

#输出以冒号分隔且第7个字段中包含/bash的行的第1个字段,~意思为包含
[root@localhost ~]# awk -F ":" '$7~"/bash"{print $1}' /etc/passwd

#输出第1个字段中包含root且有7个字段的行的第1、2个字段
[root@localhost ~]# awk -F ":" '($1~"root")&&(NF==7){print $1,$2}' /etc/passwd

#输出第7个字段既不为/bin/bash,也不为/sbin/nologin的所有行
[root@localhost ~]# awk -F ":" '($7!="/bin/bash")&&($7!="/sbin/nologin"){print}' /etc/passwd

 3.通过管道、双引号调用 Shell 命令

#输出行号和内容
[root@localhost ~]# awk '{print NR,$0}' a

#输出行号和内容
[root@localhost ~]# awk '{print NR,$0};END{print NR}' a

#以冒号为分隔符,输出内容和行号
[root@localhost ~]# echo $PATH | awk 'BEGIN{RS=":"}; {print NR,$0}'

#调用w命令,并用来统计在线用户数
[root@localhost ~]# awk 'BEGIN {n=0 ; while ("w" | getline) n++ ; {print n-2}}'

#查询用户名
[root@localhost ~]# awk 'BEGIN {"hostname" | getline ; {print $0}}'

 4.date命令输出时间

[root@localhost ~]# date -d "1 month" +"%Y/%m/%d"          #下个月的今天
[root@localhost ~]# date -d "1 month" +"%Y/%m/01"          #下个月第一天
[root@localhost ~]# date +"%Y/%m/01"                       #当月第一天
[root@localhost ~]# date -d "1 month ago" +"%Y/%m/%d"      #一个月前的今天
[root@localhost ~]# date -d "1 day ago" +"%Y/%m/%d"        #1天前
[root@localhost ~]# date -d "-1 day " +"%Y/%m/%d"          #1天前
[root@localhost ~]# date -d "$(date +%Y%m01) -1 day" +%Y/%m/%d    #上个月的最后一天
[root@localhost ~]# date -d "$(date -d "1 month" +%Y%m01) -1 day" +%Y/%m/%d  #当月最后一天

[root@localhost ~]# date -d "$(cat /proc/uptime | awk -F. '{print $1}') second ago" +"%Y%m%d %H:%M:%S"         
#显示上次系统重启时间,等同于uptime;second ago为显示多少秒前的时间,+"%F %H:%M:%S"等同于+"%Y-%m-%d %H:%M:%S"的时间格式
/proc/uptime 第一列输出的是,系统启动到现在的时间(以秒为单位);第二列输出的是,系统空闲的时间(以秒为单位)
date -d "$(date -d"1 month" +"%Y%m01") -3 day" +"%Y%m%d"  当月倒数第三天
date +"%Y%m01"        当月第一天

5. 查看内存使用占比

#内存使用率占比
[root@localhost ~]# free -m | awk '/Mem/ {print $3/$2 * 100"%"}

#内存空闲率占比
[root@localhost ~]# free -m | awk '/Mem/ {print ($2-$3)/$2 * 100"%"}'

6.查看cpu使用占比

#cpu使用率占比
[root@localhost ~]# top -b -n1 | awk -F, '/%Cpu/ {print $4}' | awk '{print 100-$1"%"}'

7.获取奇数偶数行

[root@localhost ~]# seq 10 | awk '{getline; print $0}'    #获取偶数行
[root@localhost ~]# seq 10 | awk '{print $0; getline}'    #获取奇数行
当getline左右无重定向符“<”或“|”时,awk首先读取到了第一行,就是1,然后getline,就得到了1下面的第二行,就是2,因为getline之后,awk会改变对应的NF,NR,FNR和$0等内部变量,所以此时的$0的值就不再是1,而是2了,然后将它打印出来。
当getline左右有重定向符“<”或“|”时,getline则作用于定向输入文件,由于该文件是刚打开,并没有被awk读入一行,只是getline读入,那么getline返回的是该文件的第一行,而不是隔行。

 8.OFS 输出分割符

#OFS为指定分隔符
[root@localhost ~]# echo "A B C D" | awk '{OFS="|";print $0;$1=$1;print $0}'               
#以|为分隔符输出
[root@localhost ~]# echo "A B C D" | awk '{OFS="/";print $0;$1=$1;print $0}'
#以/为分隔符输出

 9.数组

#输出数组的下标位为1的数值
[root@localhost ~]# awk 'BEGIN{a[0]=1; a[1]=2; a[2]=3; print a[1]}' 
2
#输出数组的下标位为0的数值
[root@localhost ~]# awk 'BEGIN{a[0]=1; a[1]=2; a[2]=3; print a[0]}'
1
#也可以用字符串定义数组
[root@localhost ~]# awk 'BEGIN{a["abc"]=1; a["def"]=2; a["xyz"]=3; print a["abc"]}'
1
[root@localhost ~]# awk 'BEGIN{a["abc"]=1; a["def"]=2; a["xyz"]=3; print a["xyz"]}'
3
#输出数值和下标位
[root@localhost ~]# awk 'BEGIN{a[0]=1; a[1]=2; a[2]=3; for(i in a){print i,a[i]}}'
0 1
1 2
2 3

10.查重

#查询各种数值的重复次数
[root@localhost ~]# cat test.txt | awk '{a[$1]++};END{for(i in a){print i,a[i]}}'

 11.过滤密码失败

awk '/Failed password/{ip[$11]++}END{for(i in ip){print i","ip[i],i}}' /var/log/secure | awk '$1>3{print $2}'
awk '/Invalid user/{print $10}' /var/log/secure | awk '{ip[$1]++}END{for(i in ip){print ip[i],i}}' | awk '$1>3{print $2}'

猜你喜欢

转载自blog.csdn.net/A1100886/article/details/130684780