文章目录
- 一、awk工具
- awk工作原理
- AWK程序的结构
- awk内置变量
- 二、案例
- 1.基础案列
- 2.BEGIN END 运算
- 3.数值与字符串的比较
- 4.awk高级用法
- 5. awk if语句
- 6.BEGIN END 流程
- 7.AWK 数组
- 8.awk 循环
一、awk工具
awk工作原理
当读到第一行时,匹配条件,然后执行指定动作,再接着读取第二行数据处理,不会默认输出
如果没有定义匹配条件默认是匹配所有数据行,awk隐含循环,条件匹配多少次动作就会执行多少次。
逐行读取文本,默认以空格或tab键为分隔符进行分隔,将分隔所得的各个字段保存到内建变量中,并按模式或者条件执行编辑命令。
sed命令常用于一整行的处理,而awk比较倾向于将一行分成多个"“字段"然后再进行处理。
awk信息的读入也是逐行读取的,执行结果可以通过print的功能将字段数据打印显示。
在使用awk命令的过程中,可以使用逻辑操作符”
&&“表示"与”、“||表示"或”、"!“表示非”;还可以进行简单的数学运算,如+、一、*、/、%、^分别表示加、减、乘、除、取余和乘方。
AWK程序的结构
开始块(BEGIN block)
顾名思义,开始块就是在程序启动的时候执行的代码部分,并且它在整个过程中只执行一次。一般情况
下,我们在开始块中初始化一些变量。BEGIN是AWK的关键字,因此它必须是大写的。不过,开始块部
分是可选的,你的程序可以没有开始块部分。
主体块(Body Block)
对于每一个输入的行,都会执行一次主体部分的命令。默认情况下,对于输入的每一行,AWK都会执行
命令。注意:在主体块部分,没有关键字存在。
结束块(END Block)
它是在程序结束时执行的代码。END也是AWK的关键字,它也必须大写。与开始块相似,结束块也是可
选的
AWK 工作通过三个步骤
1、读(Read):从文件、管道或标准输入中读入一行然后把它存放到内存中
2、执行(Execute):对每一行数据,根据 AWK 命令按顺序执行。默认情况是处理每一行数据,也可
以指定模式
3、重复(Repeat):一直重复上述两个过程直到文件结束
awk内置变量
awk常用内置变量:$1、$2、NF、NR、$0
$1:代表第一列
$2:代表第二列以此类推
$0:代表整行
NF:一行的列数
NR:行数
二、案例
1.基础案列
awk '{print}' passwd #打印全文
awk -F: '{print $1}' passwd #-F:以:切割,$1表示切割后只显示第一位
awk -F: '/root/{print $0}' passwd #搜索包含root的行,$0打印一整行
awk -F: '/root/{print $1,$6}' passwd #搜索包含root的行,$1,$6表示打印第一和第六列
awk -F: '{print NF}' passwd #打印每一行的列数
awk -F: '{print NR}' passwd #打印每一行的行号
awk -F: '{print NR,$0}' passwd #打印每行的行号和内容
awk 'NR==2' /etc/passwd #可以加print,也可以不加默认就是打印第二行awk 'NR==2{print}' /etc/passwd
awk -F: 'NR==2{print $1}' /etc/passwd #打印第二行第一列
awk -F: '{print $NF}' /etc/passwd #打印最后一列
awk 'END{print NR}' /etc/passwd #打印总行号(实际打印最后一行行号)
awk 'END{print $0}' /etc/passwd #打印最后一行(因为END是最后处理的,这时打印会打印最后一行)
awk -F: '/root/' /etc/passwd #打印包含root的行
awk -F: '$1~/root/' /etc/passwd #模糊查询第一列像root
awk -F: '$1~/ro/' /etc/passwd #模糊查询第一列像roawk -F: '$7!~/nologin$/{print $1,$7}' /etc/passwd
#模糊查询第一列不像nologin结尾.并且打印第一列和第七列awk -F: '{print "第"NR"行有"NF"列"}' /etc/passwd #打印每行行号和列数
ifconfig ens33 | awk '/RX p/{print $5"字节"}' #/RX p是对ens33的流量监控,显示流量多少
df -h | awk 'NR==2{print $4}' #根分区的可用量
awk ‘{print}’ passwd
awk -F: ‘{print $1}’ passwd
awk -F: ‘/root/{print $0}’ passwd
awk -F: ‘/root/{print $1,$6}’ passwd
awk -F: ‘{print NF}’ passwd
awk -F: ‘{print NR}’ passwd
awk -F: ‘{print NR,$0}’ passwd
awk ‘NR==2’ /etc/passwd
awk -F: ‘NR==2{print $1}’ /etc/passwd
awk -F: ‘{print $NF}’ /etc/passwd
awk ‘END{print NR}’ /etc/passwd
awk ‘END{print $0}’ /etc/passwd
awk -F: ‘/root/’ /etc/passwd
awk -F: ‘$1~/root/’ /etc/passwd
awk -F: ‘$1~/ro/’ /etc/passwd
awk -F: '$7!~/nologin$/{print $1,$7}' /etc/passwd
awk -F: ‘{print “第"NR"行有"NF"列”}’ /etc/passwd
ifconfig ens33 | awk ‘/RX p/{print $5"字节"}’
df -h | awk ‘NR==2{print $4}’
2.BEGIN END 运算
逐行执行开始之前执行什么任务,结束之后再执行什么任务,用BEGIN、END
BEGIN一般用来做初始化操作,仅在读取数据记录之前执行一次
END一般用来做汇总操作,仅在读取完数据记录之后执行一次
awk 'BEGIN{x=10;print x}' #BEGIN在处理文件之前,所以后面不跟文件名也不影响
awk 'BEGIN{x=10;print x+1}'
awk 'BEGIN{print x+1}' #不指定初始值,初始值就为0,如果是字符串,则默认为空
awk 'BEGIN{print 4.5-3}' #小数也可以运算
awk 'BEGIN{print 3*4}'
awk 'BEGIN{print 1/2}'
awk 'BEGIN{print 2^3}' #^和**都是幂运算
awk ‘BEGIN{x=10;print x}’
awk ‘BEGIN{x=10;print x+1}’
awk ‘BEGIN{print x+1}’
awk ‘BEGIN{print 4.5-3}’
awk ‘BEGIN{print 3*4}’
awk ‘BEGIN{print 1/2}’
awk ‘BEGIN{print 2^3}’
3.数值与字符串的比较
awk 'NR==5{print}' /etc/passwd #打印行号为5的行
awk 'NR==5' /etc/passwd #打印行号为5的行(和上个一样)
awk 'NR<5' /etc/passwd #打印行号小于5的行
awk -F: '$3==0' /etc/passwd #打印第三列等于0的行
awk -F: '$1=="root"' /etc/passwd #打印第一行等于root的行
awk -F: '$3>=1000' /etc/passwd #打印第三行大于等于1000的行
awk ‘NR==5{print}’ /etc/passwd
awk ‘NR==5’ /etc/passwd
awk ‘NR<5’ /etc/passwd
awk -F: ‘$3==0’ /etc/passwd
awk -F: ‘$1==“root”’ /etc/passwd
awk -F: ‘$3>=1000’ /etc/passwd
逻辑运算 && ||
&& 和 || 是逻辑运算符,用于组合多个条件并控制程序流程。
&& 要求所有条件都为真时才为真,否则为假。
|| 只要有一个条件为真就为真,全为假时才为假。
awk -F: '$3<10 || $3>=1000' /etc/passwd #打印第三列小于10或者大于1000的行
awk -F: '$3>10 && $3<1000' /etc/passwd #打印第三十列大于10并且小于1000的行
awk -F: 'NR>4 && NR<10' /etc/passwd #打印行号大于4小于10的行
seq 200 | awk '$1%7==0 && $1~/7/'
#seq输出一个200的序列传进awk中,$1表示序列中的每个数字,%7==0能否被7整除,并且$1~7,数字还要包含7
awk -F: ‘$3<10 || $3>=1000’ /etc/passwd
awk -F: ‘$3>10 && $3<1000’ /etc/passwd
awk -F: ‘NR>4 && NR<10’ /etc/passwd
seq 200 | awk ‘$1%7==0 && $1~/7/’
其他内置变量的用法FS(输入)、OFS、NR、FNR、RS、ORS
FS:输入字段的分隔符 默认是空格
OFS:输出字段的分隔符 默认也是空格
FNR:读取文件的记录数(行号),从1开始,新的文件重新重1开始计数
RS:输入行分隔符 默认为换行符
ORS:输出行分隔符 默认也是为换行符
awk 'BEGIN{FS=":"}{print $1}' passwd #BEGIN设置字段分隔符 FS 为冒号 :,打印第一列
awk 'BEGIN{FS=":";OFS="---"}{print $1,$2}' passwd #BEGIN额外设置输出分隔符为---
awk '{print FNR,$0}' passwd hosts #打印行号和内容,FNR是内置变量,行号为每个文件独立
awk '{print NR,$0}' passwd hosts #打印行号和内容,NR也是内置变量,但是行号是连续的
awk 'BEGIN{RS=":"}{print $0}' /etc/passwd #RS:以:为分隔符,所有以:分开的都单独看作一行
awk 'BEGIN{ORS=" "}{print $0}' /etc/passwd #ORS=" "以空格为输出行分割符
awk ‘BEGIN{FS=“:”}{print $1}’ passwd
awk ‘BEGIN{FS=“:”;OFS=“—”}{print $1,$2}’ passwd
awk ‘{print FNR,$0}’ passwd hosts
awk ‘{print NR,$0}’ passwd
awk ‘BEGIN{RS=“:”}{print $0}’ /etc/passwd
awk ‘BEGIN{ORS=" "}{print $0}’ /etc/passwd
4.awk高级用法
a=100
awk -v b="$a" 'BEGIN{print b}'
#在awk程序开始之前,设置变量b的值为shell变量的值,然后执行awk程序并打印变量b的值。awk 'BEGIN{print "'$a'"}'
awk -v c=1 'BEGIN{print c}'
#都是赋值awk 'BEGIN{getline}/root/{print $0}' passwd
#在处理任何输入之前,立即读取一行数据,然后搜索含有root的行(相当于排除第一行)seq 10 | awk '{getline;print $0}' #跳过第一行,然后打印,显示偶数行
seq 10 | awk '{print $0;getline}' #先打印,然后跳过一行,显示奇数行
a=100
awk -v b=“$a” ‘BEGIN{print b}’
awk ‘BEGIN{print "’$a’"}’
awk -v c=1 ‘BEGIN{print c}’
awk ‘BEGIN{getline}/root/{print $0}’ passwd
seq 10 | awk ‘{getline;print $0}’
seq 10 | awk ‘{print $0;getline}’
5. awk if语句
awk的if语句也分为单分支、双分支和多分支
awk -F: '{if($3<10){print $0}}' passwd
#只要第三列小于10,就打印awk -F: '{if($3<10){print $3} else{print $1}}' passwd
#第三列小于10,就打印第三列,否则就打印第一列
awk -F: ‘{if($3<10){print $0}}’ passwd
6.BEGIN END 流程
awk还支持for循环、while循环、函数、数组等awk 'BEGIN{ commands } pattern{ commands } END{ commands }'第一步:运行BEGIN{ commands }语句块中的语句。第二步:从文件或标准输入(stdin)读取一行。然后运行pattern{ commands }语句块,
它逐行扫描文件,从第一行到最后一行反复这个过程。直到文件所有被读取完成。第三步:当读至输入流末尾时,运行END{ commands }语句块。BEGIN语句块在awk开始从输入流中读取行之前被运行,这是一个可选的语句块,
比如变量初始化、打印输出表格的表头等语句通常能够写在BEGIN语句块中。END语句块在awk从输入流中读取全然部的行之后即被运行。比方打印全部行的分析结果
这类信息汇总都是在END语句块中完毕,它也是一个可选语句块。pattern语句块中的通用命令是最重要的部分,它也是可选的。假设没有提供pattern语句块,
则默认运行{ print },即打印每个读取到的行。awk读取的每一行都会运行该语句块。
这三个部分缺少任何一部分都可以
awk 'BEGIN{x=0};/\/bin\/bash$/ {x++;print x,$0};END {print x}' passwd
#设一个变量x,搜索末尾包含/bin/bash,打印自增的x和每行内容,end打印最后的xawk -F: '!($3<200){print}' passwd #打印列第三不小于200awk 'BEGIN {FS=":"} ;{if($3>=1000){print}}' passwd #先用:分割,然后打印第三列大于等于1000的行awk -F: ' {max=($3>=$4) ?$3:$4; {print max}} ' /etc/passwd #三元运算符,比较第三列和第四列的大小sed -n '=;p' /etc/passwd # =用于打印当前的行号,先打印行号,再打印内容awk -F : '$7~"bash"{print $1,$3}' /etc/passwd #搜索第七列包含像bash的内容,打印第一列和第三列awk -F: '($1~"root") && (NF==7) {print $1,$2,$NF } ' passwd #搜索第一列像root且列数为7的行,打印第一二列和最后一列awk -F : '($7!="/bin/bash")&&($7!="/sbin/nologin"){print} ' /etc/passwd #搜索第七列不包含/bin/bash和不包含/sbin/login的列awk -F: '($NF !="/bin/bash")&&($NF !="/sbin/nologin" ) {print NR, $0}' passwd #搜索最后一列不等于/bin/bash和/sbin/nologin的行echo $PATH | awk 'BEGIN{RS=":"};{print NR,$0};END {print NR}'
#将PATH传进awk中,以:开始为换行,打印每一行的行号和内容,最后打印最后一行行号free -m |awk '/Mem:/ {print int($3/($3+$4)*100)"%"}' #搜索包含Mem:的行,运算当前内存使用百分比top -b -n 1 | grep Cpu | awk -F ',' '{print $4}'| awk '{print$1}'
#top -b -n 1表示静态快照一次传给后面的管道,过滤出Cpu部分,以,分割,打印cpu的空闲率awk 'BEGIN { "hostname" | getline ; {print $0}}' #getline获取hostname的数据,然后打印
awk ‘BEGIN{x=0};//bin/bash$/ {x++;print x,$0};END {print x}’ passwd
awk -F: ‘!($3<200){print}’ passwd
awk ‘BEGIN {FS=“:”} ;{if($3>=1000){print}}’ passwd
awk -F":" ’ {max=($3>=$4) ?$3:$4; {print max}} ’ /etc/passwd
sed -n ‘=;p’ passwd
awk -F: ‘$7~“bash”{print $1,$3}’ passwd
awk -F":" ‘($1~“root”)&&(NF==7){print $1, 2. 2. 2.NF}’ passwd
awk -F : '($7!=“/bin/bash”)&&($7!=“/sbin/nologin”){print} ’ /etc/passwd
awk -F: '($NF !="/bin/bash")&&($NF !="/sbin/nologin" ) {print NR, $0}' passwd
echo $PATH | awk ‘BEGIN{RS=“:”};{print NR,$0};END {print NR}’
*free -m |awk '/Mem:/ {print int($3/($3+$4)100)“%”}’
awk ‘BEGIN { “hostname” | getline ; {print $0}}’
7.AWK 数组
awk 'BEGIN{a[0]=10;a[1]=20;print a[1]}' #打印数组下标1的内容
awk 'BEGIN{a["abc"]="aabbcc";a["xyz"]="xxyyzz";print a["xyz"]}'
awk ‘BEGIN{a[0]=10;a[1]=20;print a[1]}’
awk ‘BEGIN{a[“abc”]=“aabbcc”;a[“xyz”]=“xxyyzz”;print a[“xyz”]}’
8.awk 循环
awk 'BEGIN{a[0]=10;a[1]=20;a[2]=30;for(i in a){print a[i]}}' #循环打印数组a,在awk中i不需要定义,会自动迭代awk '{ip[$1]++;} END{for(i in ip){print ip[i],i}}' /var/log/httpd/access_log | sort -
#统计日志文件中每个 IP 地址的出现次数,ip[$1]++ 表示如果 ip 数组中已经存在键 $1(即该 IP 地址),则对应的值增加 1awk '{a[$1] += 1;} END {for (i in a) printf("%d %s\n", a[i],i);}'
#统计文本文件中每一行第一列数据的出现次数("%d %s\n" 是一个格式化字符串,这个字符串定义了如何打印数组中的元素和它们的索引)awk '/Failed password/ {print $0} ' /var/log/secure #搜索包含Failed password的行awk '/Failed/{ip[$11]++}END{for(i in ip){print i" "ip[i]}}'/var/log/secure
#ip[$11]++每出现一次1行的元素就+1,统计出现次数,for 循环的变量 i 用来表示当前遍历到的键
(awk不需要定义循环次数,它内部自己就有循环)
awk ‘BEGIN{a[0]=10;a[1]=20;a[2]=30;for(i in a){printi a[i]}}’
awk '/Failed password/ {print $0} ’ /var/log/secure
awk ‘/Failed/{ip[$11]++}END{for(i in ip){print i","ip[i]}}’/var/log/secure