菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
330
0

awk

原创
05/13 14:22
阅读数 58961

1.Awk基础介绍

2.awk语法格式

第一种形式:awk 'BEGIN{} pattern {commands} END {}' file_name
第二种形式:standard output | awk BEGIN{} pattern {commands} END {}
第三种形式:awk [options] -f awk-script-file filenames

2.Awk工作原理

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

3.Awk内部变量

$0		#将读入进来的一行数据存储至$0中,读入进来默认按行为分割由RS变量控制
$1		#经过FS变量字段分割后,将一行内容拆分成几段,分别赋值给$1 $2 $3.....
NF		#统计每一行由FS分割之后多少列,多少个字段
NR		#给每一行载入进来的内容,都添加一个编号
FS		#指定字段分隔符,默认空格为分割
RS		#指定读入进来的内容分隔符,默认按照 \n  换行符
OFS		#输出字段分割符,默认是空格为分割
ORS		#输出行分割符,默认是换行
print	#打印

4.Awk格式输出

  • 	printf
    
    
    格式符	含义
    %s		打印字符串
    %d		打印十进制数
    %f		打印一个浮点数
    %x		打印十六进制数
    %o		打印八进制数
    
    修饰符	含义
    
    -	左对齐
    
    +	右对齐
    
[root@manager awk]# awk '
BEGIN { 
	printf "%-20s%-20s%-20s%-20s\n",
	"Name","shuxue","yuwen","yinx"
} 
{
	printf "%-20s%-20s%-20s%-20s\n",  $1,$2,$3,$4
}' file3.txt

Name                shuxue              yuwen               yinx                
Oldxu               20                  30                  40                  
oldqiang            10                  5                   2                   
oldguo              1                   1                   1                   
oldgao              1                   2                   3                   
oldboy              10                  2                   0  

5.Awk模式匹配

1.正则匹配
	2.运算符   <  >      +-/*
 	3.与或非


符号	含义
<		小于
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"}$3>50{print $0}' passwd
3、以:为分隔符,匹配/etc/passwd文件中第7个字段为/bin/bash的所有行信息
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"}$7=="/bin/bash"{print $0}' passwd
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"}$7 ~/\/bin\/bash/{print $0}' passwd

4、以:为分隔符,匹配/etc/passwd文件中第7个字段不为/bin/bash的所有行信息
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"}$7!="/bin/bash"{print $0}' passwd
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"}$7 !~/\/bin\/bash/{print $0}' passwd

5、以:为分隔符,匹配/etc/passwd文件中第3个字段包含3个数字以上的所有行信息
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"}$3 ~ /[0-9]{3,}/{print $0}' passwd 
布尔运算符匹配示例
符号	含义
||		或
&&		与
!		非
1、以:为分隔符,匹配passwd文件中包含ftp或mail的所有行信息。
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"}$1=="ftp"||$1=="mail"{print $0}' passwd

2、以:为分隔符,匹配passwd文件中第3个字段小于50并且第4个字段大于50的所有行信息。
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"}$3<50 && $4>50{print $0}' passwd

3.匹配没有/sbin/nologin 的行。
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"} $0 !~ /\/sbin\/nologin/{print $0}' passwd
[root@manager awk]# awk 'BEGIN{FS=":"} $7 != "/sbin/nologin"' passwd 

a

wk的 + - * / % 支持小数
	运算符	含义

    +       加

 	-       减

   			乘
      /		除
      %		余
[root@manager awk]# cat student.txt 
oldxu       80    90    96    98
oldqiang    93    98    92    91
oldguo      78    76    87    92
oldli       86    89    68    92

oldgao      85    95    75    90
本章练习示例:
1.找出/etc/passwd文件中uid为0的。
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"}$3==0' passwd

2.找出/etc/passwd文件中uid小于10的。
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"}$3<10' passwd

3.找出/etc/passwd文件中uid 小于50,且bash为/bin/bash 的行
	awk 'BEGIN{FS=":"} $3<50 && /\/bin\/bash$/' passwd
	awk 'BEGIN{FS=":"} $3<50 && $7 == "/bin/bash"' passwd


4.匹配用户名为root并且打印uid小于15的行
	awk 'BEGIN{FS=":"} $3<15 && $1=="root"' passwd

5.匹配用户名为root或uid大于5000
	awk 'BEGIN{FS=":"} $3>5000 || $1=="root"' passwd
	

6.匹配uid为3位及以上的行
	awk 'BEGIN{FS=":"} $3 ~ /[0-9]{3,}/' passwd

7.匹配到 /sbin/nologin 的行
	awk '$0 ~ /\/sbin\/nologin/' passwd
	awk 'BEGIN{FS=":"} $7 ~ "/sbin/nologin" passwd
	awk 'BEGIN{FS=":"} $7 == "/sbin/nologin" passwd

8.磁盘使用率大于多少35092400,则打印可用的值。
	df  |awk 'NR==2 { if ($4 < 35092400) {print $4} }

9.正则匹配nginx开头的行
	awk '!/^#|^$|^ +#/' /etc/nginx/nginx.conf

翻译如下语句含义:
示例1

awk '/west/' datafile 		#从datafile文件中匹配west行

awk '/^nor/' datafile 		#从datafile文件中匹配以nor开头的行

awk '$3 ~ /^nor/' datafile 

awk '/^(no|so)/' datafile 

awk '{print $3,$2}' datafile

awk '{print $3 $2}' datafile 

awk '{print $0}' datafile 

awk '{print "Number of fields: "NF}' datafile 

awk '/nor/{print $3,$2}' datafile

awk '/^[ns]/{print $1}' datafile 

awk '$5 ~ /\. [7-9]+/' datafile 

awk '$2 !~ /E/   {print $1,$2}' datafile

awk '$3 ~ /^job/{print $3 "is a nice boy."}' datafile

awk '$8 ~ /[0-9][0-9]$/{print $8}' datafile

awk '$4 ~ /Cn$/{print "The price is $" $8 "."}' datafile

awk '/gdx/{print $0}' datafile 

awk -F: '{print "Number of fields: "NF}' /etc/passwd 

awk -F"[ :]" '{print NF}' /etc/passwd 

awk示例2
[root@oldxu ~]# cat b.txt 
oldxu:is a:good boy!
[root@oldxu ~]# awk '{print NF}' b.txt
[root@oldxu ~]# awk -F ':' '{print NF}' b.txt
[root@oldxu ~]# awk -F"[ :]" '{print NF}' b.txt
[root@chengyinwu ~/awk]# awk -F "[ :]" '{print $1}' b.txt 
oldxu
[root@chengyinwu ~/awk]# awk -F "[ :]" '{print $2}' b.txt 
is
[root@chengyinwu ~/awk]# awk -F "[ :]" '{print $3}' b.txt 
a
[root@chengyinwu ~/awk]# awk -F "[ :]" '{print $4}' b.txt 
good
[root@chengyinwu ~/awk]# awk -F "[ :]" '{print $5}' b.txt 
boy!

6.Awk条件判断

if语句格式: { if(表达式){语句;语句;... } }


1.以:为分隔符,打印当前管理员用户名称
	awk 'BEGIN{FS=":"} { if($3==0) { print $1,"是管理员"} }' /etc/passwd

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

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

4.以:为分隔符,只打印/etc/passwd中第3个字段的数值在50-100范围内的行信息
	awk 'BEGIN{FS=":"} $3>=50 && $3<100 {print $0}' /etc/passwd

if…else 语句格式: {if(表达式){语句;语句;… }else{语句;语句;…}}
统计当前的超级管理员有几个   统计当前的普通用户有多少   统计当前的系统用户有多少个
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"} {if($3==0) {print $1} else {print $7}}' passwd
[root@oldxu ~]# awk 'BEGIN {FS=":"} {if($3==0) {count++} else{i++} }' /etc/passwd
[root@chengyinwu ~/awk]# awk 'BEGIN{FS=":"} {if ($3==0) {count++} else {i++}} END {print "管理员个数:" count;print "系统用户数:"i}' passwd 
管理员个数:1
系统用户数:38

if…else if…else 语句格式: { if(表达式 1){语句;语句;… }else if(表达式 2){语句;语句;. … }else{语句;语句;… }}
1.使用awk if打印出当前/etc/passwd文件管理员有多少个,系统用户有多少个,普通用户有多少个

[root@manager awk]# cat user_total.awk 
BEGIN{
	FS=":";OFS="\n"
}

{ 
	if ($3==0) 
	     { i++ } 
	else if ($3>=1 && $3<=999)
	     { j++ }  
	else
	     { k++ }  
} 
END { 
	print i "个超级管理员", 
	j "个系统用户" ,
	 k "个普通用户"
}

1.打印/etc/passwd文件中UID小于50的、或者UID小雨50大于100、或者UID大于100的用户名以及UID。
UID<50    root    0
UID<50    bin    1
50<UID<100    nobody    99
50<UID<100    dbus    81
UID>100    systemd    192
UID>100    chrony    998

[root@chengyinwu /tmp/awk]# awk -f uid.awk passwd
[root@chengyinwu /tmp/awk]# cat uid.awk 
BEGIN {
	FS=":"
}
	{
	if ($3<50) 
	{
		printf "%-20s%-20s%-10d\n","UID<50",$1,$3
	}
	else if ($3>50 && $3<100) 
	{
		printf "%-20s%-20s%-10d\n","50<UID<100",$1,$3
	}
	else if ($3>100) 
	{
		printf "%-20s%-20s%-10d\n","UID>100",$1,$3
	}
}

2.计算下列每个同学的平均分数,并且只打印平均分数大于90的同学姓名和分数信息
[root@oldxu ~]# cat student.txt
oldxu       80    90    96    98
oldqiang    93    98    92    91
oldguo      78    76    87    92
oldli       86    89    68    92
oldgao      85    95    75    90

[root@chengyinwu /tmp/awk]# awk -f student.awk student.txt
[root@chengyinwu /tmp/awk]# cat student.awk 
BEGIN{
	printf "%-10s%-10s%-10s%-10s%-10s%-10s%-10s\n",
	"Name","yuwen","shuxue","english","it","Total","AVG"
}

{
	total=$2+$3+$4+$5
	AVG=(total)/4
	if ( AVG > 90) {
	printf "%-10s%-10d%-10d%-10d%-10d%-10d%-10.2f\n",
	$1,$2,$3,$4,$5,total,AVG
	}
}

3.统计Nginx的状态,请分别打出200类 300类 400类 500类状态 出现了多少次
[root@manager awk]# awk -f log.awk access.log
[root@manager awk]# cat log.awk 
BEGIN {
	OFS="\n"
}
{
	if($9>=200 && $9<300)
 	{i++}
	else if ($9>=300 && $9<400) {
	j++
	}
	else if ($9>=400 && $9<500) {
	k++
	}

	else if ($9>=500 && $9<600) {
	m++
	}

}
	END {
		print	"状态码:  次数", 
			"200类:"i"个",
			"300类:"j"个",
			"400类:"k"个",
			"500类:"m"个" }

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

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

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


5:打印当前系统中uid大于1000的用户
[root@manager awk]# awk 'BEGIN{FS=":"} $3>1000{print $1}' passwd

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

	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 awk]# awk 'BEGIN{FS="[: ]"} {print $4}' file1.txt

8:显示/tmp/file1.txt文件中Dan的电话号码
方法一:[root@manager awk]# awk -F "[: ]" '/Dan/ {print $4}' file1.txt
方法二:[root@manager awk]# awk 'BEGIN{FS="[: ]"}/Dan/{print $4}' file1.txt

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

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

11:显示/tmp/file1.txt文件中所有头一个月捐款$250的人名
[root@manager awk]# awk 'BEGIN{FS="[ :]"} $5 ~ /250/ {print $1,$2}' file1.txt

12:显示/tmp/file1.txt文件中Savage的全名和电话号码
[root@manager awk]# awk 'BEGIN{FS="[ :]"} /Savage/ {print $1,$2,$4}' file1.txt

13:显示/tmp/file1.txt文件中只有四个字符的名
[root@manager awk]# awk '$1 ~/^[a-zA-Z]{4}$/' file1.txt

14:以空格文分隔符将/tmp/file1.txt文件中的第一列与最后一列调换位置
[root@manager awk]# awk 'BEGIN{FS=" "}{print $NF,$1}' file1.txt

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

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

发表评论

0/200
330 点赞
0 评论
收藏
为你推荐 换一批