Lniux学习-AWK使用
AWK
AWK 与 sed 的区别
- AWK用于比较规范的文本处理,用于统计数量并输出指定字段
- sed 用于将不规范的文本,处理为比较规范的文本
AWK的字段引用和分离
- AWK也是按行读取,每行称作记录,使用空格、制表符分隔开的单词称作字段,可以自己指定分隔符来隔开字段。
- 使用$1 $2 ... $n 表示每一个字段,$0 表示一整行
- awk '{print $1,$2,$3}' filename
- awk -F "'" '/^menu/{ print $2 }' /boot/grub2/grub.cfg 以'号进行分割字段,取出文件中的内核信息
- { print x++,$2 } x++ 可以显示行数
- -F 选项用于指定分隔符
- awk -F ',' '{print $1,$2,$3}' filename
- 分隔符可以使用正则表达式表示
AWK的表达式
- 系统变量
-
FS 和 OFS 字段分隔符,OFS 表示输出的字段分隔符
- head -5 /etc/passwd | awk 'BEGIN{FS=":"}{ print $1 }'
BEGING,在读入文件之前,进行预处理。在读入passwd文件之前,就通过FS选项指定好了以“:”作为分隔符。 - head -5 /etc/passwd | awk 'BEGIN{FS=":";OFS="-"}{ print $1,$2 }' OFS="-",OFS是在查找到字段后,系统是默认使用空格进行隔开,而OFS改变了默认隔开的符号。
- head -5 /etc/passwd | awk 'BEGIN{FS=":"}{ print $1 }'
-
RS 行记录分隔符,记录行,RS 默认就是一个换行符,在多行合并成单行时,使用RS进行处理
- head -5 /etc/passwd | awk 'BEGIN{RS=":"}{ print $1 }' 系统默认的行记录分隔符是换行符,RS=":",把行记录分隔符换成:
-
NR 和 FNR 行数
- head -5 /etc/passwd | awk '{ print NR,$0 }' NR显示行号,$0显示行内容
- awk '{ print NR,$0 }' /etc/hosts /etc/hosts
- awk '{ print FNR,$0 }' /etc/hosts /etc/hosts
对单个文件,使用NR和FNR没什么区别,若是接多个文件,NR会按顺序对内容一直排序,不区分文件;FNR是以先文件进行区分,再各自进行排序。
-
NF 字段数量,最后一个字段内容可以用 $NF 取出
- head -5 /etc/passwd | awk 'BEGIN{FS=":"}{ print NF }' 输出每一行中有多少个字段
-
AWK 的条件和循环语句
条件语句格式:
If(表达式)
awk语句1
[ else
awk语句2
]
若有多个语句需要执行可以使用{}将多个语句括起来
例如:kpi.txt
user1 88 28 34 34 44
user2 45 55 22 33 66
- awk '{if($2>=80) print $1}' kpi.txt
- awk '{if($2>=80) {print $1 ; print $2} }' kpi.txt
循环语句
- while 循环格式
while(表达式)
awk 语句1
- do 循环格式
do{
awk 语句1
} while(表达式)
- for 循环格式
for{初始值;循环判断条件:累加}
awk 语句1
- head -1 kpi.txt | awk '{for(c=2;c<=NF;c++) sum+=$c;print $sum}' kpi.txt 计算第一行的kpi总值
- head -1 kpi.txt | awk '{for(c=2;c<=NF;c++) sum+=$c;print sum/(NF-1)}' kpi.txt 计算第一行的kpi平均值
- awk '{sum=0; for(c=2;c<=NF;c++) sum+=$c;print sum/(NF-1)}' kpi.txt 计算所有行各自的kpi平均值
AWK 数组
数组:一组具有某种关联的数据,可通过下标依次访问
- 数组名[下标]=值
- 下标可用数字或字符串表示
查看数组所有元素
-
for( 变量 in 数组名 )
使用 数组名[变量],依次对每个数组的元素进行操作 -
awk '{sum=0; for(c=2;c<=NF;c++) sum+=$c;avg[$1]=sum/(NF-1)} END { for(user in avg) sum12+=avg[user];print sum2/NR}' kpi.txt 计算所有人各自的平均值后,再计算总的平均值
-
awk的脚本文件以.awk结尾,加载awk脚本文件:awk -f avg.awk kpi.txt
删除数组
- delete 数组名[下标]
命令行参数数组
- ARGC:awk 后面所带的命令行参数的个数
- ARGV:具体每一个参数的内容
demo:
demo.awk 内容
BEGIN{
for (x=0;x<ARGC;x++)
print ARGV[x]
print ARGC
}
执行: awk -f demo.awk 11 22 33
awk 数据功能的使用
Demo:
统计得分的总数和平均分
score1 99 44 55 66 42
score2 90 45 67 89 32
score3 34 43 65 65 36
score4 45 76 34 34 56
{
sum = 0
for( c=2; c<=NF; c++)
# sum,每个人的总得分
sum+=$c
# avg,每个人的平均得分,NF 表示分隔的字段总数
avg[$1] = sum / ( NF-1 )
# 设置等级
if ( avg[$1] >= 80 )
letter = "S"
else if ( avg[$1] >= 70 )
letter = "A"
else if( avg[$1] >= 60 )
letter = "B"
else
letter = "C"
# 输出每个人的平均得分和等级
print $1,avg[$1],letter
# 计算相同等级的有多少个,这种方法可以使用在统计某一个IP使用的次数,某一个时间发生的次数这些场景中
letter_all[letter]++
}
END{
for ( user in avg)
# 计算所有平均值的总数
sum_all += avg[user]
# 计算总的平均得分,NR表示行数
avg_all = sum_all / NR
print "average all",avg_all
# 计算在总的平均值之下和之上各自有几个
for (user in avg)
if ( avg[user] > avg_all )
above++
else
below++
print "above",above
print "below",below
print "S:",letter_all["S"]
print "A:",letter_all["A"]
print "B:",letter_all["B"]
print "C:",letter_all["C"]
}
您对以上内容有何建议或意见,请写下来告诉我,谢谢!!!