目录
一、关于awk的基础知识
1、什么是awk
2、工作原理
3、常见的内建变量(可直接用)
二、结合简单示例,对awk进一步理解
1、打印文本内容
1.1 打印磁盘已经使用情况
1.2 打印字符串
1.3 打印字符串确定文件有多少行
2、根据$n以及NR提取字段
2.1 提取ip地址
3、根据选项-F指定分隔符
3.1 打印/etc/passwd所有用户名
3.2 打印多列内容
3.3 打印磁盘已经使用情况,去除%
3.4 取出文本中的ip地址及时间
3.5 取出文本中的主机并放回
4.、根据关键字提取所在行
4.1 提取/etc/passwd 以root开头的行
4.2 提取/etc/passwd root所在的行
4.3 提取/etc/passwd nologin结尾的行
5、使用BEGIN输出包含指定字符的行并统计有多行
6、FS:指定每行文本的字段分隔符,默认为空格或制表符,与-F相同
7、NF:当前处理行的整行内容
7.1 当前处理的行的字段个数
7.2 打印出每行最后一个字段
7.3 打印出每行倒数第二个字段
8、NR:当前处理行的行号
8.1 当前处理的行的行号
8.2 NR==n代表行号等于什么
8.3 NR%2==0取偶数行
8.4 NR%2==1取奇数行
8.5 NR==1,NR==4取区间行
8.6 取UID数值范围$n>1000
awk:Aho, Weinberger, Kernighan,报告生成器,格式化文本输出,GNU/Linux发布的AWK目前由自由软件基金会(FSF)进行开发和维护,通常也称它为 GNU AWK
有多种版本:
AWK:原先来源于 AT & T 实验室的的AWK
NAWK:New awk,AT & T 实验室的AWK的升级版
GAWK:即GNU AWK。所有的GNU/Linux发布版都自带GAWK,它与AWK和NAWK完全兼容
GNU AWK 用户手册文档
The GNU Awk User’s Guide
在 Linux/UNIX 系统中,awk 是一个功能强大的编辑工具,逐行读取输入文本,默认以空格或tab键作为分隔符作为分隔,并按模式或者条件执行编辑命令。而awk比较倾向于将一行分成多个字段然后进行处理。AWK信息的读入也是逐行指定的匹配模式进行查找,对符合条件的内容进行格式化输出或者过滤处理,可以在无交互的情况下实现相当复杂的文本操作,被广泛应用于 Shell 脚本,完成各种自动化配置任务。
前面提到 sed 命令常用于一整行的处理,而 awk 比较倾向于将一行分成多个“字段”然后再进行处理,且默认情况下字段的分隔符为空格或 tab 键。awk 执行结果可以通过 print 的功能将字段数据打印显示。
格式:
awk [options] 'program' var=value file…
说明:
program通常是被放在单引号中,并可以由三种部分组成
BEGIN语句块
模式匹配的通用语句块
END语句块
常见选项:
-F “分隔符” 指明输入时用到的字段分隔符,默认的分隔符是若干个连续空白符
-v var=value 变量赋值
Program格式:
pattern{action statements;..}
pattern:决定动作语句何时触发及触发事件,比如:BEGIN,END,正则表达式等
action statements:对数据进行处理,放在{}内指明,常见:print, printf
output statements:print,printf
Expressions:算术,比较表达式等
Compound statements:组合语句
Control statements:if, while等
input statements
执行过程:
- 第一步:执行BEGIN{action;… }语句块中的语句
- 第二步:从文件或标准输入(stdin)读取一行,然后执行pattern{ action;… }语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。
- 第三步:当读至输入流末尾时,执行END{action;…}语句块
- BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中
- END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块
- pattern语句块中的通用命令是最重要的部分,也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块
- FS∶ 列分割符。指定每行文本的字段分隔符,默认为空格或制表位。与"-F"作用相同
- NF∶ 当前处理的行的字段个数。
- NR∶ 当前处理的行的行号(序数)。
- $0∶当前处理的行的整行内容。
- $n∶ 当前处理行的第n个字段(第n列)。
- FILENAME∶ 被处理的文件名。
- RS∶ 行分隔符。awk从文件上读取资料时,将根据RS的定义把资料切割成许多条记录,而awk一次仅读入一条记录,以进行处理。预设值是’\n’
- $NF:最后一段
- $(NF-1):倒数第二段
awk可以将自动将多个空格压缩成一个空格
打印字符串需要加双引号
df |awk '{print $5}'
awk '{print "hello"}'
awk '{print "hello"}' /etc/fstab
awk '{print "hello"}' /etc/fstab |wc -l
cat /etc/fstab |wc -l
cat /etc/passwd|awk -F":" '{print $1}'
或
cat /etc/passwd|awk -F: '{print $1}'
打印时逗号可以表示空格,如果使用“:”或者“+”,需要将特殊符号加上双引号当成字符串打印
cat /etc/passwd|awk -F: '{print $1,$3}'
#指定冒号作为分隔符,打印第一列和第三列
cat /etc/passwd|awk -F: '{print $1":"$3}'
#用冒号分隔开
cat /etc/passwd|awk -F: '{print $1"\t"$3}'
#使用两条awk命令
df|awk '{print $5}'|awk -F% '{print $1}'
#使用一次awk命令
df|awk -F"[ %]+" '{print $5}'
##也可以使用( |%)代表或者
df|awk -F"( |%)+" '{print $5}'
##文本内容##
vim test.txt
58.87.87.99 - - [09/Jun/2020:03:42:43 +0800] "POST /wp-cron.php?
doing_wp_cron=1591645363.2316548824310302734375 HTTP/1.1" ""sendfileon
128.14.209.154 - - [09/Jun/2020:03:42:43 +0800] "GET / HTTP/1.1" ""sendfileon
64.90.40.100 - - [09/Jun/2020:03:43:11 +0800] "GET /wp-login.php HTTP/1.1" ""sendfileo
##提取##
cat test.txt |sed '2d'|awk -F"[[ ]" '{print $5"\t"$1}'
##文本内容##
vim host.txt
1 www.kgc.com
2 mail.kgc.com
3 ftp.kgc.com
4 linux.kgc.com
5 blog.kgc.com
##提取##
cat host.txt |awk -F "[. ]" '{print $2}' >>host.txt
cat /etc/passwd |awk -F":" '/^root/{print}'
cat /etc/passwd |awk -F: '/root/{print}'
cat /etc/passwd |awk -F":" '/nologin$/{print}'
##如果提取/sbin/nologin,则需要\转义/
cat /etc/passwd |awk -F":" '/\/sbin\/nologin$/{print}'
BEGIN模式表示,在处理指定的文本之前,需要先执行BEGIN模式中指定的动作;
awk再处理指定的文本,之后再执行END模式中指定的动作;
END{ } 语句块中,往往会放入打印结果等语句。
#先定义变量x,表示执行多少次
awk 'BEGIN {x=0};/\/bin\/bash$/;{x++};END{print x}' /etc/passwd
awk -v FS=: '{print $1FS$3}' /etc/passwd
cat /etc/passwd |awk -F: '{print NF}'
cat /etc/passwd |awk -F: '{print $NF}'
cat /etc/passwd |awk -F: '{print $(NF-1)}'
#NR写在后面则在后面显示行号
#awk -F: '{print $1,NR}' /etc/passwd
root 1
bin 2
daemon 3
adm 4
lp 5
sync 6
shutdown 7
halt 8
#可以用制表符
awk -F: '{print $1"\t"NR}' /etc/passwd
root 1
bin 2
daemon 3
adm 4
lp 5
#NR写在前面则在前面显示行号
awk -F: '{print NR"\t"$1}' /etc/passwd
1 root
2 bin
3 daemon
4 adm
5 lp
awk -F: 'NR==2 {print $1}' /etc/passwd
awk -F: 'NR%2==0 {print NR"\t"$1}' /etc/passwd
awk -F: 'NR%2==1 {print $1}' /etc/passwd
awk -F: 'NR==1,NR==4 {print $1}' /etc/passwd
#取uid大于1000的行
awk -F: '$3>1000 {print}' /etc/passwd
#取uid大于等于1000的行
awk -F: '$3>=1000 {print}' /etc/passwd