4

CentOS Linux三剑客

 2 years ago
source link: https://blog.51cto.com/baicia/5542059
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

CentOS Linux三剑客

推荐 原创

白菜素三鲜丶 2022-08-03 21:56:36 ©著作权

文章标签 sed bash 读取文件 文章分类 虚拟化 云计算 阅读数285

Linux三剑客

## 选项
-n:打印行号
-A:after 打印过滤内容的后N行
-B:before 打过过滤内容的前N行
-C:center 打印过滤内容的前后N行
-E:支持扩展正则 ere grep -E 'root|nginx' /etc/passwd
-v:取反
-o:只打印匹配到的内容
-w:精确匹配
-P:支持Perl正则
-i:忽略大小写
-r:递归检索文件的内容
-R:递归检索文件的内容,包括软链接文件
-l:只显示文件名	(配合-r选项使用)
-h:只显示文件内容	(配合-r选项使用)
-f:对比文件内容,内容少的文件在前面,内容多的文件在后面,取反可以看到不同的文件内容
-c:统计行数,类似于 wc -l
-G:支持基础正则 bre
-m:显示前N行 类似于 head -n

CentOS Linux三剑客_sed

在sed中,我们的核心内容,主要分为四个部分

sed命令执行流程

[root@web01 ~]# cat 2.txt 
/tmp/check_1.txt
/tmp/check_2.txt
/tmp/check_3.txt
/tmp/check_4.txt
/tmp/check_5.txt
/tmp/check_6.txt
/tmp/CHE_7.txt
/tmp/CHE_8.txt

执行 sed -n '2p' 2.txt命令后,sed都做了啥?

1.sed先是按行读取文件内容
2.每读取一行内容,都会进行一次判断,是不是你想要的行
3.如果不是,则判断是不是加了-n选项
4.如果加了-n,就读取下一行
5.如果没加-n,就会将所有内容输出到命令行(默认输出)
6.如果是,你想要的那一行(第二行)则判断执行的后续动作(p d s a i c)
7.动作处理完成后,输出指定的内容
8.即便是读取完了,内容也输出了,sed也会继续往后读,直到文件的最后一行

sed—查

sed命令选项 选项含义 sed命令动作 动作含义
-n 取消默认输出 p print 打印
-r 支持扩展正则 d delete 删除
a append 追加
i insert 插入
p:打印,显示

## sed显示单行内容
[root@web01 ~]# sed '2p' 2.txt 
/tmp/check_1.txt
/tmp/check_2.txt
/tmp/check_2.txt
/tmp/check_3.txt
/tmp/check_4.txt
/tmp/check_5.txt
/tmp/check_6.txt
/tmp/CHE_7.txt
/tmp/CHE_8.txt


## 取消默认输出
[root@web01 ~]# sed -n '2p' 2.txt 
/tmp/check_2.txt

## sed显示多行内容并取消默认输出
[root@web01 ~]# sed -n '2,5p' 2.txt 
/tmp/check_2.txt
/tmp/check_3.txt
/tmp/check_4.txt
/tmp/check_5.txt

## sed模糊查询
[root@web01 ~]# sed -n '/che/p' 2.txt 
/tmp/check_1.txt
/tmp/check_2.txt
/tmp/check_3.txt
/tmp/check_4.txt
/tmp/check_5.txt
/tmp/check_6.txt

[root@web01 ~]# sed -n '/C/p' 2.txt 
/tmp/CHE_7.txt
/tmp/CHE_8.txt

[root@web01 ~]# sed -nr '/che|C/p' 2.txt 
/tmp/check_1.txt
/tmp/check_2.txt
/tmp/check_3.txt
/tmp/check_4.txt
/tmp/check_5.txt
/tmp/check_6.txt
/tmp/CHE_7.txt
/tmp/CHE_8.txt

## sed 隔指定行数读取一行
[root@web01 ~]# sed -n '1~2p' 2.txt 
/tmp/check_1.txt
/tmp/check_3.txt
/tmp/check_5.txt
/tmp/CHE_7.txt
[root@web01 ~]# sed -n '2~2p' 2.txt 
/tmp/check_2.txt
/tmp/check_4.txt
/tmp/check_6.txt
/tmp/CHE_8.txt
[root@web01 ~]# sed -n '2~3p' 2.txt 
/tmp/check_2.txt
/tmp/check_5.txt
/tmp/CHE_8.txt

## sed实现grep -A(打印过滤内容的后N行)
[root@web01 ~]# sed -n '/1/,+3p' 2.txt 
/tmp/check_1.txt
/tmp/check_2.txt
/tmp/check_3.txt
/tmp/check_4.txt

[root@web01 ~]# sed -n '/3/,+2p' 2.txt 
/tmp/check_3.txt
/tmp/check_4.txt
/tmp/check_5.txt

CentOS Linux三剑客_bash_02

sed—删

d:delete 删除
## 删除指定行数,不修改原文件
[root@web01 ~]# cat 2.txt 
/tmp/check_1.txt
/tmp/check_2.txt
/tmp/check_3.txt
/tmp/check_4.txt
/tmp/check_5.txt
/tmp/check_6.txt
/tmp/CHE_7.txt
/tmp/CHE_8.txt
[root@web01 ~]# sed '2d' 2.txt 
/tmp/check_1.txt
/tmp/check_3.txt
/tmp/check_4.txt
/tmp/check_5.txt
/tmp/check_6.txt
/tmp/CHE_7.txt
/tmp/CHE_8.txt
[root@web01 ~]# cat 2.txt 
/tmp/check_1.txt
/tmp/check_2.txt
/tmp/check_3.txt
/tmp/check_4.txt
/tmp/check_5.txt
/tmp/check_6.txt
/tmp/CHE_7.txt
/tmp/CHE_8.txt

## 删除最后一行
[root@web01 ~]# sed '$d' 2.txt 
/tmp/check_1.txt
/tmp/check_2.txt
/tmp/check_3.txt
/tmp/check_4.txt
/tmp/check_5.txt
/tmp/check_6.txt
/tmp/CHE_7.txt

## -i选项,连同文本内容一同删除
[root@web01 ~]# sed -i '$d' 2.txt 
[root@web01 ~]# cat 2.txt 
/tmp/check_1.txt
/tmp/check_2.txt
/tmp/check_3.txt
/tmp/check_4.txt
/tmp/check_5.txt
/tmp/check_6.txt
/tmp/CHE_7.txt

[root@web01 ~]# sed -ri '/1/,/2/d' 2.txt 
[root@web01 ~]# cat 2.txt 
/tmp/check_3.txt
/tmp/check_4.txt
/tmp/check_5.txt
/tmp/check_6.txt
/tmp/CHE_7.txt

sed—增

## 菜(cai)

c:	replace 替换整行内容
a:	append  追加
i:	insert 插入

## c:replace 替换整行内容
[root@web01 ~]# cat 2.txt 
/tmp/check_3.txt
/tmp/check_4.txt
/tmp/check_5.txt
/tmp/check_6.txt
/tmp/CHE_7.txt
[root@web01 ~]# sed '1c1,/tmp/che_2.txt' 2.txt 
1,/tmp/che_2.txt
/tmp/check_4.txt
/tmp/check_5.txt
/tmp/check_6.txt
/tmp/CHE_7.txt

[root@web01 ~]# cat 2.txt 
/tmp/check_3.txt
/tmp/check_4.txt
/tmp/check_5.txt
/tmp/check_6.txt
/tmp/CHE_7.txt
[root@web01 ~]# sed -i '1c/tmp/che_2.txt' 2.txt 
[root@web01 ~]# cat 2.txt 
/tmp/che_2.txt
/tmp/check_4.txt
/tmp/check_5.txt
/tmp/check_6.txt
/tmp/CHE_7.txt

## a:	append  追加
[root@web01 ~]# cat 2.txt 
/tmp/che_2.txt
/tmp/check_4.txt
/tmp/check_5.txt
/tmp/check_6.txt
/tmp/CHE_7.txt
[root@web01 ~]# sed -i '1a/tmp/check_3.txt' 2.txt 
[root@web01 ~]# cat 2.txt 
/tmp/che_2.txt
/tmp/check_3.txt
/tmp/check_4.txt
/tmp/check_5.txt
/tmp/check_6.txt
/tmp/CHE_7.txt

## i:insert 插入
[root@web01 ~]# sed -i '1i/tmp/check_1.txt' 2.txt 
[root@web01 ~]# cat 2.txt 
/tmp/check_1.txt
/tmp/che_2.txt
/tmp/check_3.txt
/tmp/check_4.txt
/tmp/check_5.txt
/tmp/check_6.txt
/tmp/CHE_7.txt

sed—改

s:	substitute 替换
g:	global 全局
s###g
s@@@g
s啥都行g

## 基础用法
[root@web01 ~]# cat 2.txt 
/tmp/check_1.txt
/tmp/che_2.txt
/tmp/check_3.txt
/tmp/check_4.txt
/tmp/check_5.txt
/tmp/check_6.txt
/tmp/CHE_7.txt
[root@web01 ~]# sed -i 's#che_#CHECK_#g' 2.txt 
[root@web01 ~]# cat 2.txt 
/tmp/check_1.txt
/tmp/CHECK_2.txt
/tmp/check_3.txt
/tmp/check_4.txt
/tmp/check_5.txt
/tmp/check_6.txt
/tmp/CHE_7.txt

## 使用正则
[root@web01 ~]# sed 's#[0-9]#777#g' 2.txt 
/tmp/check_777.txt
/tmp/CHECK_777.txt
/tmp/check_777.txt
/tmp/check_777.txt
/tmp/check_777.txt
/tmp/check_777.txt
/tmp/CHE_777.txt

## 后向引用
[root@web01 ~]# ifconfig eth0|sed -nr 's#^.*inet (.*)  net.*#\1#gp'
10.0.0.7


sed的模式空间

将文件中的,所有换行符,替换成空格

N:在读取文件是,让sed把下一行内容一起读进去

awk的内置变量和动作和选项

awk内置变量 变量含义 akw选项 选项含义 awk动作 动作含义
NR Number of Record 行号 -F 指定分隔符 gsub 替换
RS Record Separator 行的分隔符(\n) -v 指定变量(内置变量、自定义变量) print 打印
FS Field Separator 列的分隔符(空格)
NF Number Of Filed 每一行有多少列

**注意:**awk输出变量使用单引号,bash输出变量使用双引号

awk不是一个命令,是一门语言

awk又叫做GNU awk,gawk

[root@web01 ~]# ls -l $(which awk)
lrwxrwxrwx. 1 root root 4 May 12 19:20 /usr/bin/awk -> gawk

awk执行流程

三个阶段

  • 读取文件之前
    • BEGIN{}
    • 1.读取文件前,先看命令的选项,例如:-F、-v
    • 2.如果写了BEGIN{},则先在BEGIN{读取}中的指令
  • 读取文件时
    • 1.awk在读取文件时,也是一行一行的读
    • 2.读取一行后,判断是否满足条件,如果是,则执行{对应动作}
    • 3.如果不满足条件,awk继续读取下一行,直到满足条件或者文件的最后一行
  • 读取文件之后
    • END{}
    • 1.所有文件读取完成之后,走END{}中的指令
[root@web01 ~]# awk 'BEGIN{xxx}{print $1}END{print 1+1}' 2.txt

[root@web01 ~]# awk -F: 'BEGIN{print "name","uid","gid"}{print $1,$2,$3,$4}END{print "已显示结果"}' /etc/passwd|column -t
name             uid  gid
root             x    0      0
bin              x    1      1
daemon           x    2      2
adm              x    3      4
lp               x    4      7
sync             x    5      0
shutdown         x    6      0
halt             x    7      0
mail             x    8      12
operator         x    11     0
games            x    12     100
ftp              x    14     50
nobody           x    99     99
systemd-network  x    192    192
dbus             x    81     81
polkitd          x    999    998
sshd             x    74     74
postfix          x    89     89
swu              x    1000   1000
rpc              x    32     32
rpcuser          x    29     29
nfsnobody        x    65534  65534
ntp              x    38     38
apache           x    48     48
www              x    666    666
已显示结果

awk的行与列

行:记录 record

列:字段 field

awk取行

NR:Number of Record

[root@web01 ~]# awk 'NR==1' /etc/passwd
root:x:0:0:root:/root:/bin/bash

## 范围取行(1-5行)
[root@web01 ~]# awk 'NR>=1 && NR<=5' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

## 范围取行(1-3)
[root@web01 ~]# awk 'NR==1,NR==3' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin

## 包含2和6内容的行
[root@web01 ~]# cat 2.txt 
/tmp/check_1.txt
/tmp/CHECK_2.txt
/tmp/check_3.txt
/tmp/check_4.txt
/tmp/check_5.txt
/tmp/check_6.txt
/tmp/CHE_7.txt
[root@web01 ~]# awk '/2|6/' 2.txt 
/tmp/CHECK_2.txt
/tmp/check_6.txt

## 第三行到最后一行
[root@web01 ~]# awk 'NR>=3' 2.txt 
/tmp/check_3.txt
/tmp/check_4.txt
/tmp/check_5.txt
/tmp/check_6.txt
/tmp/CHE_7.txt

## 显示内容1到wsh的行
[root@web01 ~]# cat 2.txt 
/tmp/check_1.txt
/tmp/CHECK_2.txt
/tmp/check_3.txt
wsh.txt
/tmp/check_4.txt
/tmp/check_5.txt
/tmp/check_6.txt
/tmp/CHE_7.txt
[root@web01 ~]# awk '/1/,/wsh/' 2.txt 
/tmp/check_1.txt
/tmp/CHECK_2.txt
/tmp/check_3.txt
wsh.txt

### awk的控制结束标记
Record Separator

[root@web01 ~]# awk -vRS=/ '{print "这是行号" NR $0}' 2.txt 
这是行号1
这是行号2tmp
这是行号3check_1.txt

这是行号4tmp
这是行号5CHECK_2.txt

这是行号6tmp
这是行号7check_3.txt
wsh.txt

这是行号8tmp
这是行号9check_4.txt

这是行号10tmp
这是行号11check_5.txt

这是行号12tmp
这是行号13check_6.txt

这是行号14tmp
这是行号15CHE_7.txt

awk取列

FS:内置变量,列分隔符  -F: = -vFS=:

[root@m01 ~]# awk -vFS=:  '{print $1}' /etc/passwd

[root@m01 ~]# awk -vFS=:  '{print $1,$NF}' /etc/passwd

[root@m01 ~]# awk -F:  '{print $1"#"$2"#"$3"#"$4"#"$5"|"$6","$NF}' /etc/passwd

## 修改输出后内容的分隔符
[root@m01 ~]# awk -F: -vOFS=# '{print $1,$2,$3,$4,$5,$6,$NF}' /etc/passwd

[root@m01 ~]# awk -F: '{print $0}' /etc/passwd

awk取行取列

## 取出top中的运行时间
[root@m01 ~]# top -n1 |awk 'NR==1{print $5}'
1

## 取出网卡配置文件的IP地址
[root@m01 ~]# awk -F= '/IPADDR/{print $2}' /etc/sysconfig/network-scripts/ifcfg-eth0
10.0.0.61

# 请找出姓氏是张的人,他们第二次捐款的数额及姓名

##### 有问题的写法  ############
[root@m01 ~]# cat user.txt
1 Zeng Laoshi       133411023        :110:100:75
2 Deng Ziqi            44002231        :250:10:88
3 Zhang Xinyu      877623568      :120:300:200
4 Gu Linazha         11029987         :120:30:79
5 Di Lireba             253097001      :220:100:200
6 Jiang Shuying    535432779       :309:10:2
7 Ju Jingyi             68005178         :130:280:385
8 Zhang Yuqi         376788757       :500:290:33
9 Wen Zhang         259872003      :100:200:300
[root@m01 ~]# awk -F '[ :]+' 'BEGIN{print "姓","名","捐款数额"}/^Zhang/{print $2,$3,$6}' user.txt 
姓 名 捐款数额
[root@m01 ~]# awk -F '[ :]+' 'BEGIN{print "姓","名","捐款数额"}/Zhang/{print $2,$3,$6}' user.txt 
姓 名 捐款数额
Zhang Xinyu 300
Zhang Yuqi 290
Wen Zhang 200

############# 正确写法  ################
[root@m01 ~]# awk -F '[ :]+' 'BEGIN{print "姓","名","捐款数额"}$2~/Zhang/{print $2,$3,$6}' user.txt 
姓 名 捐款数额
Zhang Xinyu 300
Zhang Yuqi 290

[root@m01 ~]# awk -F '[ :]+' 'BEGIN{print "姓","名","捐款数额"}$2~/Zhang/ && $3~/X/{print $2,$3,$6}' user.txt 
姓 名 捐款数额
Zhang Xinyu 300

[root@m01 ~]# awk -F '[ :]+' 'BEGIN{print "姓名","捐款数额"}$2~/Zhang/ && $3~/X/{print $2 $3,$6}' user.txt |column -t
姓名        捐款数额
ZhangXinyu  300

[root@m01 ~]# awk -F '[ :]+' 'BEGIN{print "姓名","捐款数额"}$2~/Zhang/ && $3~/X/{print $2 $3,$(NF-1)}' user.txt |column -t
姓名        捐款数额
ZhangXinyu  300



### 显示所有以25开头的QQ号及姓名
[root@m01 ~]# awk '$4~/^25/{print $2 $3,$4}' user.txt 
DiLireba 253097001
WenZhang 259872003

### 显示所有QQ号最后一位是1或者3的人,全名及QQ
[root@m01 ~]# awk '$4~/1$|3$/{print $2$3,$4}' user.txt 
ZengLaoshi 133411023
DengZiqi 44002231
DiLireba 253097001
WenZhang 259872003
[root@m01 ~]# awk '$4~/(1|3)$/{print $2$3,$4}' user.txt 
ZengLaoshi 133411023
DengZiqi 44002231
DiLireba 253097001
WenZhang 259872003
[root@m01 ~]# awk '$4~/[13]$/{print $2$3,$4}' user.txt 
ZengLaoshi 133411023
DengZiqi 44002231
DiLireba 253097001
WenZhang 259872003



### 显示每个捐款值都以$开头 $110:$00$75
[root@m01 ~]# awk  '{gsub(/:/,"$");print $0}' user.txt 
1 Zeng Laoshi       133411023        $110$100$75
2 Deng Ziqi            44002231        $250$10$88
3 Zhang Xinyu      877623568      $120$300$200
4 Gu Linazha         11029987         $120$30$79
5 Di Lireba             253097001      $220$100$200
6 Jiang Shuying    535432779       $309$10$2
7 Ju Jingyi             68005178         $130$280$385
8 Zhang Yuqi         376788757       $500$290$33
9 Wen Zhang         259872003      $100$200$300


[root@m01 ~]# awk  '{gsub(/:/,"$",$5);print $0}' user.txt 
1 Zeng Laoshi 133411023 $110 :100:75
2 Deng Ziqi 44002231 $250 :10:88
3 Zhang Xinyu 877623568 $120 :300:200
4 Gu Linazha 11029987 $120 :30:79
5 Di Lireba 253097001 $220 :100:200
6 Jiang Shuying 535432779 $309 :10:2
7 Ju Jingyi 68005178 $130 :280:385
8 Zhang Yuqi 376788757 $500 :290:33
9 Wen Zhang 259872003 $100 :200:300


function gsub(){
	$1
	$2
	$3
    xxxx
}

gsub(xx,aaa,d)



gsub("被替换的内容","替换的新内容")
gsub("被替换的内容","替换的新内容",第N列)


## 综合应用:找出ifconfig中范围是1-255的数字
[root@m01 ~]# ifconfig |awk -vRS='[^0-9]+' '$0>=1 && $0<=255'
10
61
255
255
255
10
255
6
80
20
29
3
64
20
29
3
2
5
2
6
1
172
16
1
61
255
255
255
172
16
1
255
6
80
20
29
3
9
64
20
29
3
9
46
9
117
29
7
73
127
1
255
6
1
128
10

awk模式与动作

awk -F: 'NR==1{print $1,$3}' /etc/passwd

上面这条命令我们可以看到,'NR==1{print $1,$3}'
可以理解为,'模式{动作}' == '条件{指令}'

awk中的模式

  • 正则表达式
# 正则表达式写法
'/正则表达式/flag'
'$1~/正则表达式/flag'
'$1!~/正则表达式/flag'

只不过我们在awk中很少使用flag
  • 比较表达式
NR==1
NR>=10
NR<=100
NR>=1 && NR<=10
$1>=100
## 精确匹配行号:从第10行到第20行
NR==10,NR==20

## 精确匹配字符串:从该字符串的行到另一个字符串所在行
'/root/,/zls/'
'/从哪个字符串所在行/,/到那个字符串所在行/'  #中间的行都包含进去

## 模糊匹配字符串:从含有该字符串所在行到含有另一字符串所在行
'$1~/oo/,$1~/zl/'
BEGIN
END

awk中的动作

在awk中,我们最常用的动作就是 print

当然我们还有别的动作可以使用:

  • print 打印
  • gsub 替换
useradd name;pass=`echo $RANDOM|md5sum|cut -c 1-10`;echo $pass|passwd --stdin name;echo $pass:$user >> /tmp/user.txt
seq 100|awk '{print "useradd test"$1";pass=`echo $RANDOM|md5sum|cut -c 1-10`;echo $pass|passwd --stdin test"$1";echo $pass:test"$1" >> /tmp/user.txt"}'|bash

如果要使用BEGIN模式,那么一定要成双成对的出现:BEGIN{}

那么我们要知道,BEGIN{}中,大括号里面的内容,会在读取文件内容之前执行

主要应用场景:

[root@web01 opt]# awk 'BEGIN{print 1/3}'
0.333333
  • 2.awk功能测试
  • 3.输出表格的表头

END模式

一般来说,END{}要比BEGIN{}重要一些,BEGIN{}可有可无,计算其实可以放在读取文件的时候,也可以行

END{}中,大括号里面的内容,会在awk读取完文件的最后一行后,进行处理

**作用:**一般我们使用END{}来显示对日志内容分析后的一个结果

当然,还有其他功能,比如文件读取完了,可以显示一些尾部信息

## 1.统计/etc/passwd文件中一共有多少行
[root@web01 opt]# awk '{line++;print line}' /etc/passwd
1
2
3
...
25

# 不需要过程,只显示结果
[root@web01 opt]# awk 'END{print NR}' /etc/passwd
25

### 流氓写法
[root@web01 opt]# sed -n '$=' /etc/passwd
25
[root@web01 opt]# grep -c '.*' /etc/passwd
25
[root@web01 opt]# wc -l /etc/passwd
25 /etc/passwd

## 2.统计/etc/service中空行的数量
[root@web01 opt]# awk '/^$/{i++}END{print i}' /etc/services 
17

## 3.统计出下列文件中所有人的年龄和
[root@web01 opt]# cat user.txt 
姓名      年龄
张三    23
李四    18
王五    99

# awk方式
[root@web01 opt]# awk 'NR>1{n+=$2}END{print n}' user.txt 
140

# 脚本方式
[root@web01 opt]# vim 1.sh
#!/bin/bash
n=0
for line in `cat user.txt`;do
if [[ $line =~ [0-9]+ ]];then
  ((n+=$line))
fi
done
echo $n

## 4.统计nginx日志中,状态码是200的次数以及,状态码是200时占用的流量
[root@web01 opt]# zcat blog.driverzeng.com_access.log-20220623.gz | awk 'BEGIN{print "状态码200","总流量"}$10~/200/{code++;byte+=$11}END{print code,byte}' | column -t
状态码200  总流量
3100       190477111

# 5.统计nginx日志中状态码是4xx和5xx的次数及总流量
[root@web01 opt]# zcat blog.driverzeng.com_access.log-20220623.gz | awk 'BEGIN{print "状态码200","总流量"}$10~/^[45]/{code++;byte+=$11}END{print code,byte}' | column -t
状态码200  总流量
580        519243

## 6.综合应用:分别统计每种状态码的次数和每个状态码的总流量
[root@web01 opt]# cat a.sh 
zcat blog.driverzeng.com_access.log-20220623.gz | awk '
BEGIN{
  print "状态码","总流量"
}
$10~/200/{
  i1++;n1+=$11
}
$10~/^3/{
  i2++;n2+=$11
}
$10~/^4/{
  i3++;n3+=$11
}
$10~/^5/{
  i4++;n4+=$11
}
END{
  print "这是200的次数"i1,"200的总流量"n1
  print "这是3xx的次数"i2,"3xx的总流量"n2
  print "这是4xx的次数"i3,"4xx的总流量"n3
  print "这是5xx的次数"i4,"5xx的总流量"n4
}' | column -t

awk数组

在awk中的数组数据类型,是非常好用的一个类型,不像是shell,当然shell中数组也有它自己的优点

awk中的数组,专门用来统计不同的分类

例如:

1.nginx日志中每个IP出现的次数
2.nginx日志中每种状态码出现的次数
3.nginx日志中每个URI的访问次数

[root@web01 opt]# zcat blog.driverzeng.com_access.log-20220623.gz | awk '{print $1}' | sort | uniq -c| sort -nr

awk数组赋值

[root@web01 opt]# awk 'BEGIN{array[0]="wsh";array[1]="www"}'

awk数组取值

[root@web01 opt]# awk 'BEGIN{array[0]="wsh";array[1]="www";print array[0],array[1]}'
wsh www

shell循环数组

[root@web01 opt]# vim 1.sh 
#!/bin/bash
array[0]='wsh'
array[1]='www'

for name in ${array[*]};do
  echo $name
done
[root@web01 opt]# sh 1.sh 
wsh
www

awk循环数组

for(条件){
    动作
}

for 条件;do
	动作
done

[root@web01 opt]# awk 'BEGIN{array[0]="wsh";array[1]="www";for(num in array){print num}}'
0
1

[root@web01 opt]# awk 'BEGIN{array[0]="wsh";array[1]="www";for(num in array){print array[num]}}'
wsh
www

## 统计nginx日志中的每一个IP地址访问的次数
[root@web01 opt]# zcat blog.driverzeng.com_access.log-20220623.gz | awk '{array[$1]++}END{for(ip in array){print ip,array[ip]}}'

## 1.取出下列域名并根据域名,进行统计排序处理
[root@web01 opt]# cat 1.txt 
https://blog.driverzeng.com/index.html
https://blog.driverzeng.com/1.html
http://post.driverzeng.com/index.html
http://mp3.driverzeng.com/index.html
https://blog.driverzeng.com/3.html
http://post.driverzeng.com/2.html

[root@web01 opt]# cat 1.txt | awk -F/ '{print $3}'| sort | uniq -c
      3 blog.driverzeng.com
      1 mp3.driverzeng.com
      2 post.driverzeng.com

[root@web01 opt]# awk -F/ '{domain[$3]++}END{for(name in domain){print name,domain[name]}}' 1.txt
blog.driverzeng.com 3
post.driverzeng.com 2
mp3.driverzeng.com 1


## 2.统计nginx日志中,每个IP访问使用的流量总和
[root@web01 opt]# zcat blog.driverzeng.com_access.log-20220623.gz | awk '{ip[$1]++;liulaing[$1]+=$11}END{for(i in ip){print i,ip[i],liulaing[i]}}'

awk的判断

awk判断与shell判断对比

## shell
if [ 条件 ];then
	动作
fi

if [ 条件 ];then
else
fi

if [ 条件 ];then
elif [ 条件 ];then
else
fi

## awk
if(条件){
    动作
}

if(条件){
    动作
}else{
    动作
}

if(条件){
    动作
}else if(条件){
    动作
}else{
    动作
}


awk '{}END{for(条件){if(条件){动作}else if(条件){动作}else{动作}}}'
awk '{
    读文件的动作
}END{
    for(条件){
        if(条件){
            动作
        }else if(条件){
            动作
        }else{
            动作
        }
    }
}'


## 判断磁盘使用率大于70%,大于显示磁盘空间不足,不大于显示正常
# 取出磁盘使用率
[root@web01 opt]# df -h|awk -F '[ %]+' 'NR==2{if($5>70){print "磁盘空间不足"}else{print "磁盘空间还行"}}'
磁盘空间还行
[root@web01 opt]# df -h|awk -F '[ %]+' 'NR==2{if($5>70){print "磁盘空间不足"}else{print "磁盘空间还行,当前磁盘使用率:"$5"%"}}'
磁盘空间还行,当前磁盘使用率:0%

# 1.从1加到100
[root@m01 ~]# awk 'BEGIN{for(i=1;i<=100;i++){sum+=i}{print sum}}'
5050


#2.企业面试题:统计每个学生的总成绩和平均成绩
stu01 70 80 90 100 90 80
stu02 89 78 98 67 97 90
stu03 56 12 33 44 55 66 77
stu04 89 78 77 99 100       30          
stu05 98 97 96 95 94 93
stu06 100 20 20 20 20 20


[root@m01 ~]# awk 'BEGIN{print "学生姓名","总成绩","平均成绩"}{n=0;for(i=2;i<=NF;i++){n+=$i};{print $1,n,n/(NF-1)}}' 1.txt 
学生姓名 总成绩 平均成绩
stu01 510 85
stu02 519 86.5
stu03 343 49
stu04 473 78.8333
stu05 573 95.5
stu06 200 33.3333
  • 收藏
  • 评论
  • 分享
  • 举报

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK