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改变了默认隔开的符号。
    • 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"]

}
posted @ 2020-04-25 15:53  chenzy01  阅读(157)  评论(0编辑  收藏  举报