awk概述
awk是由其三个创始人姓氏的首字母拼接而来( Alfred Aho 、Peter Weinberger 和 Brian Kernighan)。
awk,报告生成器,格式化文本输出,GNU/Linux发布的awk目前有自由软件基金会(FSF)进行开发和维护,通常也称它为GNU AWK
可以使用"rpm -qi gawk"查看一段awk的官方描述“The gawk package contains the GNU version of AWK text processing utility. AWK is a programming language designed for text processing and typically used as a dataextraction and reporting tool”
重点“AWK is a programming language… ”翻译:“AWK一门编程语言”…NB,原来是一门编程语言,所以这么牛掰。难怪是三剑客之首。
GNU AWK使用手册:
https://www.gnu.org/software/gawk/manual/gawk.html
https://man7.org/linux/man-pages/man1/awk.1p.html
[root@rocky ~]# ll `which awk`
lrwxrwxrwx. 1 root root 4 May 19 2021 /usr/bin/awk -> gawk
[root@rocky ~]# rpm -qi gawk
Name : gawk
Version : 4.2.1
Release : 2.el8
Architecture: x86_64
Install Date: Tue 02 Apr 2024 05:41:55 PM CST
Group : Unspecified
Size : 2699078
License : GPLv3+ and GPLv2+ and LGPLv2+ and BSD
Signature : RSA/SHA256, Wed 19 May 2021 01:32:23 PM CST, Key ID 15af5dac6d745a60
Source RPM : gawk-4.2.1-2.el8.src.rpm
Build Date : Wed 19 May 2021 10:35:13 AM CST
Build Host : ord1-prod-x86build001.svc.aws.rockylinux.org
Relocations : (not relocatable)
Packager : infrastructure@rockylinux.org
Vendor : Rocky
URL : https://www.gnu.org/software/gawk/
Summary : The GNU version of the AWK text processing utility
Description :
The gawk package contains the GNU version of AWK text processing utility. AWK is
a programming language designed for text processing and typically used as a data
extraction and reporting tool.
The gawk utility can be used to do quick and easy text pattern matching,
extracting or reformatting. It is considered to be a standard Linux tool for
text processing.
awk功能
gawk:模式扫描和处理语言,可以实现下面功能
1.文本处理
2.输出格式化的文本报表
3.执行算数运算
4.执行字符串操作
man awk
NAME
gawk - pattern scanning and processing language
SYNOPSIS
gawk [ POSIX or GNU style options ] -f program-file [ -- ] file ...
gawk [ POSIX or GNU style options ] [ -- ] program-text file ...
......
格式
awk [options] 'program' var= value file....
awk [options] -f programfile var= value file...
说明
program通常是放在单引号中,并可以由三种部分组成
1.EGNIN语句块
2.模式匹配的通用语句块
3.END语句块
常用选项
-F "分隔符"指明输入时用到的字段分隔符,默认的分隔符是若干个连续空白符
-v var=value 变量赋值
program格式:
pattern{action statements;...}
pattern: 决定动作语句何时触发事件,比如:BEGIN,END,正则表达式等
action statements:对数据进行处理,放在{}内指明,常见:print,printf
awk工作过程
第一步:执行BEGIN{action;....}语句块中的语句;
第二步:从文件或标准输入(stdin)读取一行,然后部行pattern{ actijon..}语句块,
它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。
第三步:当读至输入流末尾时,执行END{action;..}语句块
BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,
比如变量初始化、打印输出表格的表头等语句,通常可以写在BEGIN语句块中。
END语句块在awk从输入流中读取完所有的行之后即被执行,
比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块。
pattern语句块中的通用命令是最重要的部分,也是可选的。
如果没有提供pattern语句块,则默认执行{print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块
分隔符、域和记录
1.由分隔符分隔的字段(列column,域field)标记$1,$2..$n称为域标识,$0为所有域,
注意:和shell中变量$符含义不同
2.文件的每一行称为记录record
3.如果省略action,则默认执行print $0的操作
awk的基本使用
动作print
格式
print item1,item2,...
说明:
1.必须指定FORMAT
2.不会自动换行,需要显式给出换行控制符\n
3.FORMAT中需要分别为后面每个item指定格式符
以上截图可以看出,固定字符串需要使用双引号,而数字运算和变量则不需要使用双引号。
由上例可以看出"awk ‘{print “hello world”}’"是一个标准输入命令,那么就可以使用标准输入重定向
awk中打印字符串一定要使用""双引号,
其实java也一样,双引号括起来的都是字符串,否则awk视之为变量。
[root@rocky8 ~]# awk --help
Usage: awk [POSIX or GNU style options] -f progfile [--] file ...
Usage: awk [POSIX or GNU style options] [--] 'program' file ...
POSIX options: GNU long options: (standard)
-f progfile --file=progfile
-F fs --field-separator=fs
-v var=val --assign=var=val
Short options: GNU long options: (extensions)
-b --characters-as-bytes
-c --traditional
-C --copyright
-d[file] --dump-variables[=file]
-D[file] --debug[=file]
-e 'program-text' --source='program-text'
-E file --exec=file
-g --gen-pot
-h --help
-i includefile --include=includefile
-l library --load=library
-L[fatal|invalid] --lint[=fatal|invalid]
-M --bignum
-N --use-lc-numeric
-n --non-decimal-data
-o[file] --pretty-print[=file]
-O --optimize
-p[file] --profile[=file]
-P --posix
-r --re-interval
-s --no-optimize
-S --sandbox
-t --lint-old
-V --version
awk默认文本中的分隔符
查看磁盘利用率时,df命令格式化输出了6列信息,可以看出这6列信息使用空格隔开。
awk则可以自动识别以空格或tab键分割的列,
awk中使用$1,$2,$3...$5..$n等表示第几列
取出/etc/passwd中的用户名和uid
统计出现次数最多的前几名IP
使用awk筛选
awk '{print $1}' /data/nginx.access.log-20230721 |sort |uniq -c|sort -nr|head -3
使用cut筛选
cut -d" " -f1 /data/nginx.access.log-20230721 |sort |uniq -c|sort -nr|head -3
取出分区利用率的数字
提取网卡配置文件中的ip地址
ifconfig ens160 | sed -n '2p' | awk '{print $2}'
awk常见内置变量
awk中的变量分为:内置和自定义变量
awk内置变量可以使用man帮助查看使用说明
摁“/”开始搜索关键字,
摁“n(小写)”查看下一个匹配,
摁“N(大写)”查看上一个匹配)
[root@rocky8 ~]# man awk
FS
The input field separator, a space by default. See Fields, above.
FS The input field separator, a space by default. See Fields, above.
FS:输入字段分隔符,默认为空白字符,功能相当于-F
-F fs --field-separator=fs
选取/etc/passwd文件中的第一个单词
awk -v FS=":" '{print $1}' /etc/passwd
虽然"-F"也能达到"FS"一样的的效果,但是要知道这两者有着本质上的区别,
"FS"是变量,是变量就可以在不同的地方引用,而"-f"就不行。
/etc/passwd文件的内容中,使用“:”做分隔的较多,那么我在输出打印时,我可以继续引用"FS=":""这个变量作为我输出内容的格式分隔符。
OFS
OFS The output field separator, a space by default.
OFS:输出字段分隔符,默认空白字符。
RS
RS The input record separator, by default a newline.
RS:输入记录record分隔符,指定输入时的换行符。
将";"分号作为分隔符,换行输出内容。
awk -v RS=";" '{print}' test.txt
ORS
ORS The output record separator, by default a newline.
ORS:输出记录分隔符,输出时用指定符号代替换行符
awk -v RS=";" -v FS="," -v ORS="->" '{print $1}' test.txt
NF
NF The number of fields in the current input record.
NF:当前输入记录中的字段数。
以":“分隔的有7个字段,”$NF"则是最后一个字段的值
awk -F: '{print $NF}' /etc/passwd
取出连接状态信息
netstat -nta | awk '{print $NF}'
取/etc/passwd文件的倒数第二个字段
NR
NR The total number of input records seen so far.
NR:输出记录的行号。
FNR
FNR The input record number in the current input file.
FNR:各文件分别计数,记录的行号。
ARGC和ARGV
输出参数的个数和具体的参数
模式pattern
PATTERN:根据pattern条件,过滤匹配到的行,在做处理
1.如果未指定:空模式,匹配每一行
1.如果未指定:空模式,匹配每一行
例如:awk -F: '{print $1,$3}' /etc/passwd
2./regular expression/:仅处理能够模式匹配到的行,需要用//括起来
2./regular expression/:仅处理能够模式匹配到的行,需要用//括起来
例如:awk '/UUID/{print $1}' /etc/fstab
awk '!/UUID/{print $1}' /etc/fstab "!为取反"
3.relational expression:关系表达式,结果为“真”才会被处理
真:结果为非0值,非空字符串
假:结果为0值或空字符串
4.line ranges: 行范围
不支持直接用行号,但可以使用变量NR间接指定行号
/part1/,/part2/ 不支持直接给出数字格式
打印/etc/passwd文件中以b开头到h结尾的行
条件判断if-else
[root@rocky8 ~]# awk 'BEGIN{score=88;if(score>=80){print "good"}else if(score>=60){print "pass"}else{print "no pass"}}'
good
[root@rocky8 ~]# awk 'BEGIN{score=78;if(score>=80){print "good"}else if(score>=60){print "pass"}else{print "no pass"}}'
pass
[root@rocky8 ~]# awk 'BEGIN{score=58;if(score>=80){print "good"}else if(score>=60){print "pass"}else{print "no pass"}}'
no pass
[root@rocky8 ~]#
[root@rocky8 ~]# cat score.txt
name score
zhangsan 100
lisi 90
zhaoliu 70
wangwu 55
[root@rocky8 ~]# awk 'NR!=1{score=$2;if(score>=80){print $1,"good"}else if(score>=60){print $1, "pass"}else{print $1, "no pass"}}' score.txt
zhangsan good
lisi good
zhaoliu pass
wangwu no pass
[root@rocky8 ~]#
while循环
[root@rocky8 ~]# awk 'BEGIN{i=1;sum=0;while(i<=100){sum+=i;i++};print sum}'
5050
[root@rocky8 ~]# sum=0;for((i=1;i<=100;i++));do let sum+=i;done;echo $sum
5050
[root@rocky8 ~]#