功能:汇总、处理数据,对数据进行整理
概述:
awk的名称来自于最初设计者
Alfred V. Aho
J. Weinberger
Brian W. Kernighan
awk最原始的版本是1977年在AT&T贝尔实验室诞生的,awk经过改进生成的新的版本nawk,gawk,现在默认linux系统下日常使用的是gawk.
工作流程:
逐行扫描文件,从第一行开始,到最后一行
匹配符合条件的行,在这些行上做指定的操作
基本结构:
模式{动作}
两种特殊模式
BEGIN
放在读取数据之前执行
一般用来打印表头,初始化分隔符,定义变量
END
所有数据读取完之后执行
汇总
在读取文件内容前,执行BEGIN后面的指令
然后读文件内容并判断是否满足特定的模式,如果满足,执行模式后面的指令
最后执行END模式指定
基本语法:
awk [选项] ‘/模式匹配/{处理动作1,处理动作2…}’ 文件名
awk的变量
内置变量
$0 表示一整行内容
$1-$100
$1 表示第一个字段
$2 表示第二个字段
例子:awk的简单操作
[root@ops14 20200803]# cat test
Renxiang is a good boy.
Today is Monday.
[root@ops14 20200803]# awk ‘{print $1}’ test
Renxiang
Today
[root@ops14 20200803]# awk ‘{print $2}’ test
is
is
[root@ops14 20200803]# awk ‘{print $3}’ test
a
Monday.
与记录相关的变量(记录就是行)
FS:读取文件的分隔符(输入分隔符,默认是空格)
OFS:输出字段的分隔符(输出分隔符,默认是空格)
RS:记录的分隔符(行分隔符,默认是换行符)
ORS:输出记录分隔符
例子:
输出/etc/passwd文件中的用户名和家目录,中间用@分割
awk ‘BEGIN{FS=":";OFS="@"}{print $1,$6}’ /etc/passwd
练习:
输出/etc/passwd文件中的用户名和默认shell,用~分割
例子:RS(行分隔符,默认是换行符)
[root@ops14 20200803]# cat test
Renxiang is a good boy.
Today is Monday.
[root@ops14 20200803]# awk ‘BEGIN{RS=" "}{print $0}’ test
Renxiang
is
a
good
boy.
Today
is
Monday.
[root@ops14 20200803]# awk ‘BEGIN{ORS=";"}{print $0}’ test
Renxiang is a good boy.;Today is Monday.;[root@ops14 20200803]#
练习:
test2内容如下:
name:aaa,email:[email protected],name:bbb,email:[email protected],
要求用awk进行处理,读文件时把逗号当成换行符
与数据相关的变量
NR 行号,每处理完一行,NR+1
FNR 行号,处理多个文件时,把两个文件的行号分开计算
NF 当前行的字段数
$NF 当前行的最后一个字段
$(NF-1) 当前行的倒数第二个字段
查看IP地址
ifconfig | head -2 | tail -1 | tr -s " " | cut -d " " -f 3
ifconfig | awk ‘NR==2{print $2}’
FILENAME 显示文件名
[root@ops14 20200803]# cat haha
aa
bb
ccc
dd
[root@ops14 20200803]# cat heihei
111
2222
33
44
555
6666
[root@ops14 20200803]# awk ‘{print FILENAME,NR,$0}’ haha heihei
haha 1 aa
haha 2 bb
haha 3 ccc
haha 4 dd
heihei 5 111
heihei 6 2222
heihei 7 33
heihei 8 44
heihei 9 555
heihei 10 6666
[root@ops14 20200803]# awk ‘{print FILENAME,FNR,$0}’ haha heihei
haha 1 aa
haha 2 bb
haha 3 ccc
haha 4 dd
heihei 1 111
heihei 2 2222
heihei 3 33
heihei 4 44
heihei 5 555
heihei 6 6666
自定义变量
两种定义方式
第一种 -v 变量名=变量值
第二种 在模式中直接定义
注意:给字符串赋值,一定要有双引号
变量名:数字、字母、下划线组成,不能以数字开头,不能是关键字
第一种
awk -v xx=“wo shi renxiang” ‘BEGIN{print xx}’
第二种
awk ‘BEGIN{xx=“renxiang”;print xx}’
[root@ops14 20200803]# cat student
printf 格式化输出,默认不换行
语法:
printf 格式 变量
格式都是%开头,后面跟一个字符
%s 字符串
%d 十进制整数
%f 浮点数
%x 十六进制
%o 八进制
-左对齐,默认是右对齐
%4.2f 4代表宽度,2代表2位小数
例子:
格式化输出用户名和UID
awk ‘BEGIN{FS=":"}{printf"%-20s%d\n",$1,$3}’ /etc/passwd
格式化输出用户名和家目录
awk ‘BEGIN{FS=":"}{printf"%-20s%s\n",$1,$6}’ /etc/passwd
printf总结:
1、使用printf需要指定格式
2、格式是用来指定后面每个变量的输出方式
3、printf不会自动换行,需要手动添加\n
4、printf默认不输出字符的分隔符
比较表达式
用来比较数字或字符串
=
<
<=
==
!=
例子:
1、打印/etc/passwd中UID为0的行
awk ‘BEGIN{FS=":"}$3==0’ /etc/passwd
2、找出默认shell是/bin/bash的用户
awk ‘BEGIN{FS=":"}$7=="/bin/bash"’ /etc/passwd
3、打印/etc/passwd文件中GID为1000的行
awk ‘BEGIN{FS=":"}$4==1000’ /etc/passwd
4、找出系统中的普通用户(UID>=1000)
awk ‘BEGIN{FS=":"}$3>=1000’ /etc/passwd
条件表达式
语法:
awk [选项] ‘{if(条件表达式){操作1}else{操作2}}’
例子:当UID0时,打印“管理员用户,否则,打印“普通用户”
awk -F : '{if($30){print $1"是管理员"}else{print $1"是普通用 户"}’ pass10
awk ‘BEGIN{FS=":"}{if($3==0){print $1"是管理员"}else{print $1 “是普通用户”}}’ pass10
算术运算
逻辑运算
&&
||
!
1、/etc/passwd中UID大于100且小于1000的用户
awk -F : ‘$3>100 && $3<1000 {print $1,$3}’ /etc/passwd
3、UID大于100或默认shell是/sbin/nologin的用户
awk -F “:” ‘$3>100 || $7=="/sbin/nologin"’ /etc/passwd
模式匹配
x~/y/ 匹配正则,y是正则表达式
例子:在/etc/passwd中查找用户名包含o的行
awk -F : ‘$1~/o/{print $0}’ /etc/passwd
查找默认shell是bash结尾的行
awk -F : ‘ 7 / b a s h 7~/bash 7 /bash/{print $0}’ /etc/passwd
x!~/y/ 不匹配正则
在/etc/passwd中查找用户名包含o的行
awk -F : ‘$1!~/o/’ /etc/passwd
1-100中不包含7的数字
seq 100 | awk ‘$1!~/7/’
常见的模式
空模式
匹配所有的行
例子:打印所有用户的用户名
awk -F : ‘{print $1}’ pass10
固定模式
查找默认shell是/bin/bash的行
awk -F : ‘$7~//bin/bash/’ /etc/passwd
范围模式
(sed支持用行号或者正则指定地址)
awk不支持行号定界
查找以bin开头的行到adm开头的行
awk -F : ‘/bin/,/adm/’ /etc/passwd
特殊模式
BEGIN
在没有读取任何数据之前执行
一般用于打印表头、 初始化分隔符、定义变量
END
在所有数据读取完之后执行
汇总数据