三剑客之首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{} 处理完所有匹配数据后执行
含义解释:
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的和,请使用while、for两种循环方式实现
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"}'
技术是没有终点的,也是学不完的,最重要的是活着、不秃。 学习看书还是看视频,都不重要,重要的是学会,欢迎关注,我们的目标---不秃。
---更多运维开发交流及软件包免费获取请加V: Linuxlaowang
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .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 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义