三剑客——AWK

功能:汇总、处理数据,对数据进行整理
概述:
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

  1. du 70 80 90
  2. ren 80 80 80
  3. xiang 90 90 90
    [root@ops14 20200803]# cat student.awk
    BEGIN{print"学号\t姓名\t语文\t数学\t英语\t总分\t"}
    {printf"%-s\t%-s\t%-d\t%-d\t%-d\t%-d\n",$1,$2,$3,$4,$5,sum=$3+$4+$5}

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($3
0){print $1"是管理员"}else{print $1"是普通用 户"}’ pass10

awk ‘BEGIN{FS=":"}{if($3==0){print $1"是管理员"}else{print $1 “是普通用户”}}’ pass10

算术运算

      • / %
        例子:
        打印100以内能被7整数的数字
        seq 100 | awk ‘$1%7==0{print}’

逻辑运算
&&
||
!
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
在所有数据读取完之后执行
汇总数据

你可能感兴趣的:(linux)