三剑客之首awk(包含数组的使用)

1.Awk基础介绍
1.什么是awk
awk不仅仅是一个文本处理 工具,通常用于处理数据并生成结果报告。当然awk也是一门编程
言,是Iinux上功能最强大的数据处理工具之一。
2.awk语法格式
第一种形式: awk ' BEGIN{} pattern {commands} END {}' file_ name
第二种形式:|standard output | awk BEGIN{} pattern {commands} END {}
第三种形式: awk [options] -f awk-script-file filenames

语法格式 含义
BEGIN {} 正式处理数据之前执行
pattern 匹配模式
{commands} 处理命令,可能多行
END{} 处理完所有匹配数据后执行

1573093689050

含义解释:
BEGIN发现在读文件之前,所有会在处理之前就执行了1/2。
{}表示处理文件的过程,由于文件内有三行,所以会执行三次print。
END{}表示文件处理完毕后的动作。

Awk_工作原理
# awk -F: ' {print $1,$3} ' /etc/ passwd
1.awk将文件中的每一行作为输入,并将每一行赋给内部变量$0,以换行符结束
2.awk开始进行字段分解,每个字段存储在已编号的变量中,从$1开始[默认空格分割]
3.awk默认字段分隔符是由内部Fs变量来确定,可以使用-F修订
4.awk行处理时使用了print函数打印分割后的字段
5.awk在打印后的字段加_上空格,因为$1,$3之间有一个逗号。逗号被映射至oFs内部变量中,称为输出字段分隔符, OFs默认为空格.
6.awk输出之后,将从文件中获取另一行,并将其存储在$0中,覆盖原来的内容,然后将新的字符串分
隔成字段并进行处理。该过程将持续到所有行处理完毕.

$0整行的内容
$1$2
FS字段分隔符
OFS输出字段分隔符
print输出内容
NR为每一行内容赋上编号2
NF统计字段分割后有多少列


3.Awk内部变量
内置量			含仪
$0			整行内容
$1-$n		当前行的第1-n个字段
NF			当前行的字段个数,也就是多少列
NR			当前的行号,从1开始计数
FS			输入字段分隔符。不指定默认以空格或tab键分割
RS			输入行分隔符。默认回车换行
OFS			输出字段分隔符。默认为空格
ORS			输出行分隔符。默认为回车换行

要想了解awk的一些内部变量需要先准备如下数据文件。
[root@oldxu ~]# cat awk_ file. txt
11 1990 50 51 61
kk 1991 60 52 62
hh 1992 70 53 63
jj 1993 80 54 64
mm 1994 90 55 65
1. awk内置变量, $0保存当前记录的内容
[root@oldxu ~]# awk '{print $e}' /etc/passwd
2.awk内置变量, FS指定字段分割符,默认以空白行作为分隔符
#1.输出文件中的第一列
[root@o1dxu ~]# awk '{print $1}' awk_ file. txt
11
kk
hh
mm
[ root@manager awk]# awk ' BEGIN{FS="[: ]+"} {print $1, $2}' file. txt
11 1990
kk 1991
hh 1992
jj 1993
mm 1994
[ root@manager awk]# cat file. txt
ll: 1990 50 51 61
kk:  1991 60 52 62
hh 1992 70 53 63
jj 1993 80 54 64
mm 1994 90 55 65

3.awk内置变量NF ,保存每行的最后-列
#1.通过print打印,NF和$NF,你发现了什么?
[root@o1dxu ~]# awk '{print NF, $NF}' awk_ file. txt
5 61
562
563
564
565
#F:如果将第五行的55置为空,那么该如何在获取最后一列的数字?
[root@oldxu ~]# awk '{print $5}' awk_ file. txt
61
62
63
64
#最后一列为空,为什么?

awk内置变量RS ,行分隔符。
[root@oldxu ~]# cat file. txt
Linux |She1l |Nginx--docker |Gitlab ljenkins--mysql |redis |mongodb
[root@oldxu ~]# awk 'BEGIN{RS="--"}{print $0}' file. txt
Linux |Shell |Nginx
docker | Gitlab |jenkins
mysq1 |redis I mongodb

awk内置变量, OFS指定输出字段分隔待,初始情况下OFS变量是空格。
[root@oldxu ~]# awk 'BEGIN{RS="--";FS="|";OFS=":"} {print $1,$3}' file. txt
Linux :Nginx
docker:jenkins
mysq1 :mongodb
  • printf
awk可以通过printf函数生成非常漂亮的数据报表。
格式符					含义
%s					打印字符串
%d					打印十进制数
%f					打印个浮点数
%x					打印十六进制数
%o					打印八进制数

修饰符				       含义
:						左对齐
+						右对齐


1.printf默认没有分隔符。
[root@oldxu ~]# apk 'BEGIN{FS=":"}{printf $1}' /etc/passwd
rootbindaemonadm
2.加入换行,格式化输出。
[root@oldxu ~]# awk 'BEGIN{FS= ":"}{printf "%s\n",$1}' /etc/passwd
root
bin
daemon
adm
3.使用占位符美化输出。
[root@oldxu ~]# awk ' BEGIN{FS=":"} {printf "%20s %20s\n" ,$1,$7}' /etc/passwd
root	/bin/bash
bin		/sbin/nologin
daemon	/sbin/nologin
adm	/sbin/nologin


  • awk模式匹配
awk第一种模式匹配 ; RegExp
awk第二_种模式匹配:关系运算匹配
RegExp示例
1.匹配etc/passwd文件行中含有root字符串的所有行。
[root@oldxu ~]# awk ' BEGIN{FS=”: "}/root/{print $0}' passwd
2.匹配etc/passwd文件行中以root开头的行。
[root@oldxu ~]# awk '/^root/{print $0}' passwd
3.匹配etc/passwd文件行中/bin/bash结尾的行。
[root@o1dxu ~]# awk '/\/bin\/bash$/{print $0}' passwd


运算符匹配示例

符号   		   含义
<				小于
>				大于
<= "			小于等于
>=				大于等于
==				等于
!=				不等于
~				匹配正则表达式
!~				不匹配正则表达式
1、以:为分隔符,匹配/etc/passwd文件中第3个字段小于50的所有行信息
[root@oldxu ~]# awk ' BEGIN{FS=": "}$3<50{print $3}' passwd
1、以:为分隔符,匹配/etc/passwd文件中第3个字段大于50的所有行信息
[root@oldxu ~]# awk 'BEGIN{FS= ”: "}$3>50{print $3}' passwd
3、以: 为分隔符,匹配etc/passwd文件中第7个字段为/bin/bash的所有行信息
[root@o1dxu ~]# awk ' BEGIN{FS=": "}$7=- "/bin/bash"{print $3}' passwd
4、 以为分隔符,匹配etc/passwd文件中第7个字段不为/bin/bash的所有行信息
[root@oldxu ~]# awk ' BEGIN{FS=”: "}$7!="/bin/bash"{print $3}' passwd
5、以为分隔符,匹配etc/passwd文件中第3个字段包含3个数字以上的所有行信息
[root@o1dxu ~]# awk ' BEGIN{FS=":"}$3 ~ /[0-9]{3,}/{print $3}' passwd
  • 布尔运算


1、以:为分隔符,匹配passwd文件中包含ftp或mai1的所有行信息。
[root@oldxu ~]# awk ' BEGIN{FS=":"}$1=="ftp" | | $1=="mail" {print $0} ' passwd
2、以:为分隔符,匹配passwd文件中第3个字段小于50并且第4个字段大于50的所有行信息。
[root@oldxu ~] # awk ' BEGIN{FS=":"}$3<50 && $4>50{print $0} ' passwd
3.匹配没有/sbin/nologin|的行。I
[ root@oldxu ~]# awk ' BEGIN{FS=":"} $0 !~ /\/sbin\/ nologin/ {print $0}' passwd




  • 判断
Awk条件判断
if语句格式{if(表达式{语句;语句... } }
1.以为分隔符,打印当前管理员用户名称



3.以:为分隔符,统计普通用户数量
awk 'BEGIN{FS=":"} { if ($3>=1000) { i++ } } END { print i,"个普通用户"} /etc/passwd

  • while循环
while循环: while(条件表达式动作)
[root@oldxu ~]# awk 'BEGIN{ i=1; while(i<=1e){print i; i++} }'
[root@oldxu ~]# awk -F: '{i=1; while(i<=NF){print $i; i++}}' /etc/passwd
[root@oldxu ~]# awk -F: '{i=1; while(i<=10) {print $e; i++}}' /etc/passwd
[root@oldxu ~]#cat b. txt
111 222
333444 555
666 777 888 999
[root@o1dxu ~]# awk '{i=1; while(i<=NF){print $i; i++}}' b.txt

for循环: for(初始化计数器计数器测试;计数器变更动作)
#C风格for
[root@oldxu ~]# awk ' BEGIN{for(i=1;i<=5;i++){print i} }' 
#将每行打印10次
[root@o1dxu ~]# awk -F: '{ for(i=1;i<=10;i++) {print $e} }' passwd
[root@o1dxu ~]# awk -F: '{ for(i=1;i<=10;i++) {print $e} }' passwd
[root@o1dxu ~]# awk -F: '{ for(i=1;i<=NF;i++) {print $i} }' passwd M
需求:计算1+2+3+4+... +100的和,请使用whilefor两种循环方式实现
BEGIN {
	for (i=1;i<=100;i++) {
		sum+=i
	}
	print "sum: " sum
}
--------------------------------------
BEGIN {
	i=1;
	while (i<=100)
	{
	    sum+=i
	    i++
	}
	
	print "sum: " sum
}


awk数组概述

1.什么是awk数组
	数组其实也算是变量,传统的变量只能存储一个值 ,但数组可以存储多个值。
2.awk数组应用场景
	通常用来统计、比如:统计网站访问TOP10、网站Ur访问TOP10等等等
3.awk数组统计技巧
	01.在awk中,使用数组时,不仅可以使用1 2 3.n作为数组下标,也可以使用字符串作为数组下标。
	02.要统计某个字段的值,就将该字段作为数组的索引,然后对索引进行遍历。
4.awk数组的语法
	array_ name[index]=value
5.awk数组示例
[root@manager awk]# cat array_awk_1 
BEGIN {
	#指定分隔符
	FS=":"
}

	#遍历所有的文件行
{
	#设定数组,如果数组的索引相同则自增
	shells[$NF]++

}
	#等待行遍历完成,然后在进行循环统计
END{
	#遍历数组,将数组的索引赋值给item
	for ( item in shells ) {

		#打印数组的索引,打印数组索引对应的次数,
		print item , shells[item]
	}
}
	#最后就完成了统计
	
	
1.统计访问TOP10的IP地址
[ root@manager nginx] #cat ngx_ ip_ top_ 10
{
ips [$1] ++
		}
END{
	for(item in ips)} {
		print item, ips [item]
}
}
[ root @manager nginx]# awk -f ngx_ ip_ top_ 10 access.log| sort -k 2 -rn|head

2.统计访问TOP10的IP地址 筛选大于1000的
[rootamanager nginx]# cat ngx_ _ip_ top_ 10_ 2
{
ips [$1]++
}
END{
for(item in ips){
if ( ips[item] > 10000) {
print item, ips[item]
	}
}
}
3、统计访问最多的10个页面
「root@manager nginx]# cat ngx url top 10
{
	url [$7 ] ++
}
END{
	for(item in url){
		print item, url [item]
	}
}

3、统计访问最多的10个页面,url大于1000
[ root@manager nginx]# cat ngx_ url_top 10 2
{
	urt[$7 ] ++
END{
	for(iteminurl){
		if ( urL[item] > 1000) {
		print item, url [item]
	}
}

4、统计每个URL访问内容总大小
{
	#计算每次次数
	count[$7]++
	url[$7]+=$10	#将$10赋值给url,进行叠加,相同的url,让他们的大小相加
}
END {
    for (item in url){
    	if (url[item]/1024/1024>1.5){
        print  count,[item],item, url [item]/1024/1024 "Mb"
  					  }
  	  }
    }
5、多条件(上题阐述)
[ rootamanager awk]# cat array_awk 3
{
#统计大小
	count["/run/Lvm/Lvmetad.jpg"]=10
	url["/run/Lvm/Lvmetad.jpg" ]+=1000000000
}
END{ 
	for ( item in count ){
		print item, count[item], url[item]
	}
}

6、统计状态码404出现的次数
{
    url ["404"]+=i
}
END {
	for (item in url){
        print item, url[item]
	}
}

awk练习(数组与基础)

1、计算/etc/passwd中所有用户的UID平均数,以及GID平均数

[root@10 awk]# cat  zm1.awk
BEGIN {
	FS=":"
}

{
	user[$1]++
	uid[$1]+=$3
	gid[$1]+=$4
}

END {
	for (item in uid) {
	print "UID_avg:" uid[item] / user[item], "   " 
			"GID_avg:" gid[item]/user[item]
	
	
	}

}
2、统计/etc/fstab 文件中每个文件系统类型出现的次数
	[root@manager awk]# awk '/^UUID/,/^\/dev\//{acc[$3]++}END{for(i in acc){print i,acc[i]}}' /etc/fstab

[root@10 awk]# cat  zm2.awk
{
	zm[$3]++

}

END {
	for (item in zm) {
	print item,		 zm[item]
	
	}

}


3、统计/etc/fstab 文件中每个单词出现的次数
awk '{for(i=0;i<=NF;i++){count[$i]++}}END{for(i in count){print i,count[i]}}' /etc/fstab

{
        for (i=1;i<=NF;i++) {
        fs[$i]++

        }
}

END {
        for (item in fs) {

        print item,"   "fs[item]

        }

}


4、提取出字符串Yd$C@M05MB%9&Bdh7dq+YVixp3vpw中的所有数字
awk 'gsub("[^0-9]","")'  number.txt 
echo "Yd$C@M05MB%9&Bdh7dq+YVixp3vpw"|awk -F "[^[:digit:]]"'{for(k=1;k<=NF;k++){count[$k]}}END{for(i in count){printf
 "%s",i}printf   "\n"}'
5、统计netstat -tan 中各状态的次数.
netstat -tan|awk '/^tcp/{state[$NF]++}END{for(i in state){print i,state[i]}}'



{
        state[$6]++


}

END {
        for (item in state) {
                print item," "state[item]

        }


}
[root@manager awk]# netstat -tan |awk -f 5.awk 
LISTEN 7
ESTABLISHED 1
established) 1
Foreign 1



5、统计出/etc/passwd文件中shell的种类和个数
BEGIN {
	FS=":"
}

{
	shell[$7]++

}

END {
	for (item in shell) {
	print item," "shell[item]
	}

}

[root@manager awk]# awk -f awk5.awk /etc/passwd
/bin/sync 1
/bin/bash 710
/sbin/nologin 27
/sbin/halt 1
/sbin/shutdown 1



6、统计ps aux 中VSZ,RSS各自总和
{
                user[$1]++
                VSZ[$1]+=$5
                RSS[$1]+=$6
                total_VSZ+=$5
                total_RSS+=$6

                }

END {
        for (item in VSZ) {
        print  item,"     "VSZ[item],"     "RSS[item]


        }
}


7、统计/etc/fstab 文件中每个单词出现的次数
{
        for (i=1;i<=NF;i++) {
        fs[$i]++

        }
}

END {
        for (item in fs) {

        print item,"   "fs[item]

        }

}
8、统计access.log文件中2015年11月22日的访问量
BEGIN {
        FS="[ :]"

}
{

        if ($0 ~ "22/Nov/2015") {
                tj[$4]++

        }
}

END {
        for (item in tj) {
                print item," "tj[item]

        }

}

awk -f lx7.awk access.log 

9、使用awk计算0加到100
BEGIN {

        for (i=0;i<=100;i++) {
                sum+=i

        }
        print "sum:" sum

}


10、计算/etc/ssh/sshd.config文件中所有以#开头的行数
{
        if ($1 ~ /^#/) {
        i++

        }
}
END {

        print i

}


11、统计access.log访问日志流量排名前10个IP

{
        IP[$1]++
}
END {
        for (item in IP) {
        print item,"    "IP[item]

        }
}

12、统计access.log文件中使用的流量总和

{
        IP[$1]++
        ll[$1]+=$10
}
END {
        for (item in IP) {
        print item,"    "IP[item],"   "ll[item]

        }
}

13、统计access.log文件中每种请求的数量(如GET)

{
        get[$6]++

}

END {
        for (item in get) {
        print item,get[item]
        }

}

14、统计access.log文件中每个小时的访问量


15、统计access.log文件使用哪一种浏览器的用户最多
{
        type[$25]++

}
END {
        for (item in type) {
        print item,type[item]
        }

}
 awk -f lx14.awk access.log  |sort -k2 -nr |head

 
 
---------------------------------------
awk基础题
---------------------------------------
1:若内存剩余小于200M则输出“NO”
[root@manager zh]# free -m |awk 'BEGIN{NR==2} $4<800{print "NO"}'

2:若硬盘剩余大于20G则输出“yes”
[root@manager zh]#  df -h |awk 'NR==6 { if ($4 > 20) {print "yes"}}'
yes

3:打印access.log中下载文件大小超过5M的行

5:打印当前系统中uid大于1000的用户

6:显示当前系统中容量使用率大于5%的文件系统名称和挂载点
[root@manager zh]# df -h |awk '{if($5>5){print $1,$NF}}'
Filesystem on
/dev/sda3 /

文件:
	[root@manager zh]# cat /tmp/file1.txt
	Mike Harrington:[510] 548-1278:250:100:175
	Christian Dobbins:[408] 538-2358:155:90:201
	Susan Dalsass:[206] 654-6279:250:60:50
	Archie McNichol:[206] 548-1348:250:100:175
	Jody Savage:[206] 548-1278:15:188:150
	Guy Quigley:[916] 343-6410:250:100:175
	Dan Savage:[406] 298-7744:450:300:275
	Nancy McNeil:[206] 548-1278:250:80:75
	John Goldenrod:[916] 348-4278:250:100:175
	Chet Main:[510] 548-5258:50:95:135
	Tom Savage:[408] 926-3456:250:168:200
	Elizabeth Stachelin:[916] 440-1763:175:75:300
7:显示/tmp/file1.txt文件中所有电话号码
[root@manager zh]# awk 'BEGIN{FS="[: ]"} {print $4}' file1.txt

8:显示/tmp/file1.txt文件中Dan的电话号码
[root@manager zh]# awk 'BEGIN{FS="[: ]"}/Dan/{print $4}' file1.txt
9:显示/tmp/file1.txt文件中Susan的名字和电话号码
[root@manager zh]# awk -F "[ :]" '/Susan/ {print $1,$2,$4}' file1.txt
	Susan Dalsass 654-6279

10:显示/tmp/file1.txt文件中所有区号为916的人名
 awk 'BEGIN{FS="[ :]"} /\[916\]/ {print $1,$2}' file1.txt
[root@manager zh]# awk 'BEGIN{FS="[ :]"} /\[916\]/ {print $1,$2}' file1.txt 
	Guy Quigley
	John Goldenrod
	Elizabeth Stachelin

11:显示/tmp/file1.txt文件中所有头一个月捐款$250的人名
[root@manager zh]# awk 'BEGIN{FS="[ :]"} $5 ~ /250/ {print $1,$2}' file1.txt 
	Mike Harrington
	Susan Dalsass
	Archie McNichol
	Guy Quigley
	Nancy McNeil
	John Goldenrod
	Tom Savage

12:显示/tmp/file1.txt文件中Savage的全名和电话号码
[root@manager zh]# awk 'BEGIN{FS="[ :]"} /Savage/ {print $1,$2,$4}' file1.txt
	Jody Savage 548-1278
	Dan Savage 298-7744
	Tom Savage 926-3456


13:显示/tmp/file1.txt文件中只有四个字符的名
[root@manager zh]#  awk '$1 ~/^[a-zA-Z]{4}$/' file1.txt
	Mike Harrington:[510] 548-1278:250:100:175
	Jody Savage:[206] 548-1278:15:188:150
	John Goldenrod:[916] 348-4278:250:100:175
	Chet Main:[510] 548-5258:50:95:135


14:以空格文分隔符将/tmp/file1.txt文件中的第一列与最后一列调换位置
[root@manager zh]# awk 'BEGIN{FS=" "}{print $NF,$1}' file1.txt
548-1278:250:100:175 Mike
538-2358:155:90:201 Christian
654-6279:250:60:50 Susan
548-1348:250:100:175 Archie
548-1278:15:188:150 Jody
343-6410:250:100:175 Guy
298-7744:450:300:275 Dan
548-1278:250:80:75 Nancy
348-4278:250:100:175 John
548-5258:50:95:135 Chet
926-3456:250:168:200 Tom
440-1763:175:75:300 Elizabeth



15:使用awk取出IP地址
[root@manager zh]# ifconfig eth0 |awk 'NR==2{print $2}'
10.0.0.61

16:使用awk取出/etc/passwd第一列数据也就是取出用户名。
[root@manager zh]#  awk 'BEGIN{FS=":"}{print $1}' passwd




[root@manager zh]#cat reg.txt 
Zhang	Dandan		41117397	:250:100:175
Zhang	Xiaoyu		390320151	:155:90:201
Meng	Feixue		0042789		:250:60:50
Wu   	Waiwai		70271111	:250:80:75
Liu		Bingbing	41117483	:250:100:175
Wang  	Xiaoai		3515064655	:50:95:135
17:用awk获取reg.txt文件中第三行的倒数第二列字段
[root@manager zh]# awk 'NR==3 {print $3}' reg.txt 
0042789
18:显示文件reg.txt所有以41开头的ID号码的人的全名和ID号码
[root@manager zh]# awk  '$3~/^41/{print $1,$2,$3}' reg.txt
Zhang Dandan 41117397
Liu Bingbing 41117483

19:显示小雨的姓名与id号
[root@manager zh]# awk '$2~/Xiaoyu/{print $1,$2,$3}' reg.txt 
Zhang Xiaoyu 390320151

20:显示Xiaoyu的捐款.每个值时都有以$开头.如$520$200$135
[root@manager zh]# awk -F: -vOFS="$" '$NF{print $2,$3,$4}' reg.txt 
250$100$175
155$90$201
250$60$50
250$80$75
250$100$175
50$95$135

21:提取出字符串Yd$C@M05MB%9&Bdh7dq+YVixp3vpw中的所有数字
echo "Yd$C@M05MB%9&Bdh7dq+YVixp3vpw"|awk -F "[^[:digit:]]"'{for(k=1;k<=NF;k++){count[$k]}}END{for(i in count){printf
 "%s",i}printf   "\n"}'
posted @   老王教你学Linux  阅读(723)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示