Bootstrap

awk命令详解

目录

一、awk概述

1.工作原理

2.语法格式

 3.awk常用的内建变量

二、按行输出文本

1.输出所有内容

2.输出指定行号的内容

3.输出奇偶行内容

4.输出匹配行的行内容

二、按字段输出文本

1.输出指定字段

2.输出结果指定分隔符

2.1OFS指定输出结果分隔符

3.输出匹配字段的行内容

4.三元运算符

三、通过管道符、双引号调用shell命令

1.统计行数

2.查看当前内存使用百分比

3.查看当前cpu空闲率

4.显示系统上次重启时间

5.getline的使用

四、BEGIN,END模式

 1.awk数组

2.过滤文本中重复行数

3.过滤访问本机密码输入失败的命令


一、awk概述

AWK是一种处理文本文件的语言,是一个强大的文件分析工具。

它是专门为文本处理设计的编程语言,也是行处理软件,通常用于扫描,过滤,统计汇总等工作,数据可以来自标准输入也可以是管道或文件。

1.工作原理

awk逐行读取文本,默认以空格或Tab键为分隔符进行分隔,将分隔所得的各个字段保存到内建变量中,并按模式或条件执行编辑命令。

与sed命令相比:

  • sed命令常用于一整行的处理。
  • awk命令倾向于将一行分成多个“字段” 然后再进行处理。awk信息的读入是逐行读取的,执行结果可以通过 print 的功能将字段数据打印显示。在使用 awk 命令的过程中,可以使用逻辑操作符“&&”表示“与”,“||”表示“或”,“!”表示“非”;还可以进行简单的数学运算,如+、-、*、/、%、^分别表示加、减、乘、除、取余和乘方。

2.语法格式

awk 选项 '模式或条件 {操作}' 文件1 文件2

awk -f 脚本文件 文件1 文件2

 3.awk常用的内建变量

FS:列分隔符。指定每行文本的字段分隔符,默认为空格或制表位,与“ -F ”作用相同

OFS:输出分隔符。指定输出字段间的分隔符。

RS:行分隔符。awk从文件读取资料时,将根据RS的定义把资料切割为多条记录,
awk一次仅读取一条记录,以进行处理,预设值为 \n (换行符)

NF:当前处理行的字段个数

NR:当前处理行的行号

FNR:awk当前读取的记录数,其变量值小于等于NR
(比如当读取第二个文件时,FNR是从0开始重新计数,而NR不会)。

NR==FNR:用于在读取两个或两个以上的文件时,判断是不是在读取第一个文件

$0:当前处理行的整行内容

$n:当前处理行的第 n 个字段(第 n 列)

FILENAME:被处理的文件名

二、按行输出文本

1.输出所有内容

awk '{print}' a.txt   或
awk '{print $0 }' a.txt
abc
two
three
four
five
six
seven
eight
nine
ten
eleven
twelve

2.输出指定行号的内容

#打印1-3行的行内容
awk 'NR==1,NR==3{print $0}' a.txt
one
two
three
#打印1-3行的行内容,&&表示“与”
awk '(NR>=1)&&(NR<=3){print $0}' a.txt
one
two
three
#打印第1行或第3行的行内容,|| 表示“或”
awk 'NR==1||NR==3{print $0}' a.txt
one
three
#打印行号小于4的行内容,!表示取反
awk '!(NR>4){print $0}' a.txt
one
two
three
four

3.输出奇偶行内容

#输出奇数行,行号取余=1为奇数行
awk '(NR%2)==1{print $0}' a.txt
one
three
five
seven
nine
eleven
#输出偶数行
awk '(NR%2)==0{print $0}' a.txt
two
four
six
eight
ten
twelve

4.输出匹配行的行内容

#输出以 n 开头的行内容
awk '/^n/{print $0}' a.txt
nine
#输出以 e 结尾的行内容
awk '/e$/{print $0}' a.txt
one
three
five
nine
twelve

二、按字段输出文本

1.输出指定字段

# -F 指定分隔符;$1 所在行以分隔符分隔的第一个字段
awk -F ":" '{print $1}' passwd
root
daemon
adm
y
named
lisi
apache
dhcpd
# $NF 表示所在行最后一个字段,NR 表示当前行的行号
awk -F ":" '{print NR,$NF }' passwd
1 /bin/bash
2 /sbin/nologin
3 /sbin/nologin
4 /bin/bash
5 /sbin/nologin
6 /bin/bash
7 /sbin/nologin
8 /sbin/nologin

2.输出结果指定分隔符

#输出第1和第3个字段,输出结果默认以 空格 分隔
awk -F ":" '{print $1,$3 }' passwd
root 0
daemon 2
adm 3
y 1000
named 25
lisi 1001
apache 48
dhcpd 177

awk -F ":" '{print $1","$3 }' passwd
root,0
daemon,2
adm,3
y,1000
named,25
lisi,1001
apache,48
dhcpd,177

awk -F ":" '{print $1"=="$3 }' passwd
root==0
daemon==2
adm==3
y==1000
named==25
lisi==1001
apache==48
dhcpd==177

2.1OFS指定输出结果分隔符

echo 'A B C D' | awk '{OFS=":";print $0}'
A B C D
# $1=$1 用来激活$0的重新赋值,通常是在改变OFS后而需要输出$0时这样做
echo 'A B C D' | awk '{OFS=":";$1=$1;print $0}'
A:B:C:D

3.输出匹配字段的行内容

cat passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
y:x:1000:1000:y:/home/y:/bin/bash
named:x:25:25:Named:/var/named:/sbin/nologin
lisi:x:1001:1001::/home/lisi:/bin/bash
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
dhcpd:x:177:177:DHCP server:/:/sbin/nologin
#输出第3字段大于50的行的第1和第3字段
awk -F ":" '$3>50{print $1,$3}' passwd
y 1000
lisi 1001
dhcpd 177
#输出第7字段中包含/bash的行内容
awk -F ":" '$7~"/bash"{print $0}' passwd
root:x:0:0:root:/root:/bin/bash
y:x:1000:1000:y:/home/y:/bin/bash
lisi:x:1001:1001::/home/lisi:/bin/bash

4.三元运算符

条件表达式?值1:值2

若条件表达式成立,则取值1;反之,取值2。

awk -F ":" '{print $3,$4}' passwd
0 0
2 2
3 4
1000 1000
25 25
1001 1001
48 48
177 177
#三元运算符,如果第3个字段的值大于等于第4个字段的值,则把第3个字段的值赋给max,
#否则第4个字段的值赋给max
awk -F ":" '{max=($3>=$4)?$3:$4;{print max}}' passwd
0
2
4
1000
25
1001
48
177

三、通过管道符、双引号调用shell命令

1.统计行数

awk -F ":" '/bash$/{print}' passwd 
root:x:0:0:root:/root:/bin/bash
y:x:1000:1000:y:/home/y:/bin/bash
lisi:x:1001:1001::/home/lisi:/bin/bash
#调用 wc -l 统计使用bash的行数
awk -F ":" '/bash$/{print|"wc -l"}' passwd 
3

2.查看当前内存使用百分比

#查看当前内存使用百分比
free -m | awk '/Mem:/{print int($3/($3+$4)*100)"%"}'
87%

3.查看当前cpu空闲率

# -b -n 1 表示只需要1次输出结果
top -b -n 1 | grep Cpu
%Cpu(s):  2.9 us,  2.9 sy,  0.0 ni, 96.9 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 
#输出cpu空闲率的字段
top -b -n 1 | grep Cpu | awk -F "," '{print $4}'
96.9 id
#输出Cpu空闲率
top -b -n 1 | grep Cpu | awk -F "," '{print $4}' | awk '{print$1}'
96.9

4.显示系统上次重启时间

date -d      #显示字符串所指的日期与时间。字符串前后必须加上双引号

date +"%Y-%m-%d"      #注意 :+ 和格式之间没有空格

常用格式:

%F:完整日期格式,等价于%Y-%m-%d

%Y:年份

%m:月份

%d:按月计的日期

%T:时间,等于%H:%M:%S

%H: 小时,24小时制(00~23)

%M:分钟

%S:秒

#查看当前时间
date 
2023年 05月 15日 星期一 16:24:53 CST

#显示当月的第一天
date +"%Y%m01"
20230501

#显示一天前
date -d "1 day ago" +%F
2023-05-14

#显示当月的倒数第三天,1 month 表示下个月的今天,-3 day 表示三天前
date -d "$(date -d "1 month" +"%Y%m01")-3 day" +"%Y%m%d"
20230529

#查看上次系统重启时间
#/proc/uptime 第一列输出的是,系统启动到现在的时间(以秒为单位);
#第二列输出的是,系统空闲的时间(以秒为单位)
date -d "$(awk -F "." '{print $1}' /proc/uptime) second ago" +"%F %H:%M:%S"
2023-05-11 02:15:22

5.getline的使用

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

#当有重定向符号或 “|” 时,只会输出第1行
awk 'BEGIN {"cat a.txt" |getline; {print }}'
one

#当有重定向符号或 “|” 时,输出奇数行
cat a.txt | awk '{print $0;getline}'
one
three
five
seven
nine
eleven
#输出偶数行
cat a.txt | awk '{getline;print $0}'
two
four
six
eight
ten
twelve

四、BEGIN,END模式

BEGIN模式:在处理指定文本之前,需要先执行BEGIN模式中的指定的操作。

END模式:在处理指定文本结束后,需要执行END模式中的指定操作

awk '/e$/{print $0}' a.txt
one
three
five
nine
twelve
#统计以 e 结尾的行
awk 'BEGIN{x=0}; /e$/{x++};END{print x}' a.txt
5
#先处理完BEGIN的内容,再打印文本里面的内容
awk 'BEGIN{FS=":"};{if($3>=20){print}}' passwd
y:x:1000:1000:y:/home/y:/bin/bash
named:x:25:25:Named:/var/named:/sbin/nologin
lisi:x:1001:1001::/home/lisi:/bin/bash
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
dhcpd:x:177:177:DHCP server:/:/sbin/nologin

#统计以冒号分隔的文本段落数,END{}语句块中,往往会放入打印结果等语句
echo $PATH | awk 'BEGIN{RS=":"}{print NR,$0};END{print NR}'
1 /usr/local/sbin
2 /usr/local/bin
3 /usr/sbin
4 /usr/bin
5 /root/bin

5

 1.awk数组

#BEGIN中的命令只执行一次
awk 'BEGIN{a[0]=1;a[1]=2;a[2]=3;print a[2]}'
3
#awk数组的下标除了数字,还可以使用字符串,字符串需要使用双引号
awk 'BEGIN{a["q"]="aaa";a["m"]="bbb";a["y"]="ccc";print a["q"]}'
aaa

awk 'BEGIN{a["q"]=1;a["m"]=2;a["y"]=3;for(i in a){print i,a[i]}}'
y 3
m 2
q 1

2.过滤文本中重复行数

cat b.txt
aaa
bbb
ccc
aaa
aaa
aaa
bbb
bbb
ccc
#将文本的内容作为数组下标,a[$1]++表示出现相同的行,就自加1
awk '{a[$1]++}END{for (i in a){print i,a[i]}}' b.txt
aaa 4
ccc 2
bbb 3

3.过滤访问本机密码输入失败的命令

#过滤密码输出错误的IP地址及输入次数
awk '/Failed password/{ip[$11]++}END{for(i in ip){print i,ip[i]}}' 
/var/log/secure 
192.168.88.121 4
192.168.88.20 6

#过滤输入次数大于4次的IP地址
awk '/Failed password/{ip[$11]++}END{for(i in ip){print i,ip[i]}}' 
/var/log/secure | awk '$2>4{print $1}'
192.168.88.20

;