awk

awk的概述:
   awk是一种编程语言,软件级别等同于bash,主要用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。它在命令行中使用,但更多是作为脚本来使用。awk的处理文本和数据的方式是这样的,它逐行扫描文件,默认从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作。如果没有指定处理动作,则把匹配的行显示到标准输出(屏幕),如果没有指定模式,则所有被操作所指定的行都被处理。awk分别代表其作者姓氏的第一个字母。因为它的作者是三个人,分别是Alfred Aho、Brian Kernighan、Peter Weinberger。gawk是awk的GNU版本,它提供了Bell实验室和GNU的一些扩展。下面介绍的awk是以GNU的gawk为例的,在linux系统中已把awk链接到gawk,所以下面全部以awk进行介绍。

awk命令两种使用方式:
1)命令模式
  awk [options] 'commands' file(s)
   command 部分:/范围说明(或者正则表达式)/{awk命令语句1;awk命令语句2;}
    范围说明部分可以是BEGIN、END、逻辑表达式或者为空
    awk命令语句间用分号间隔
    引用shell 变量需用双引号引起
   option 部分
    -F 定义字段分割符号
  
2)脚本模式
  awk [options] -f scriptfile file(s)
  特点:
   awk脚本是awk命令的清单
   命令需要用分号间隔
   #号开头的是注释行
   # /bin/awk -f
 
字段及分割
 awk 用$1,$2,$3...$n等的顺序形式表示files中每行以间隔符号分割的各列的不同字段
 $0表示文本本身
 awk默认以空格符为间隔符号将每行分割为单独的字段,也可以使用awk内置变量FS定义间隔符号
 awk 使用option中的-F参数定义默认间隔符号
 NF变量表示当前记录的字段数(列数)
 $NF 最后一列
 $(NF-1) 倒数第二列
 FNR/NR 行号
 FILENAME 文件名
 "\t" 制表符
 RS 换行符
 "" 打印字符串
# awk 'BEGIN {FS=":"} {print $1}' /etc/passwd
$ head -5 /etc/passwd > passwd
$ awk -F':' '{print FILENAME,FNR,NF,$1,$2,$3,$4,$5,$6,$7,"\t"$0}' ./passwd
./passwd 1 7 root x 0 0 root /root /bin/bash       root:x:0:0:root:/root:/bin/bash
./passwd 2 7 bin x 1 1 bin /bin /sbin/nologin      bin:x:1:1:bin:/bin:/sbin/nologin
./passwd 3 7 daemon x 2 2 daemon /sbin /sbin/nologin    daemon:x:2:2:daemon:/sbin:/sbin/nologin
./passwd 4 7 adm x 3 4 adm /var/adm /sbin/nologin        adm:x:3:4:adm:/var/adm:/sbin/nologin
./passwd 5 7 lp x 4 7 lp /var/spool/lpd /sbin/nologin    lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
# tail /var/log/messages | awk '{print $1,$2,$3"\t"$4"\t"$5}' | sed 's/.$//' | sed -e 's/.//15' -e 's/.//14' -e 's/.//13'
tail /var/log/messages | awk -F':| +' '{print $1,$2,$3":"$4,$6,$7}'
Aug 27 10:31 instructor named[3089]
Aug 27 10:31 instructor named[3089]
Aug 27 10:31 instructor named[3089]
 
打印所有行
$ cat passwd
$ awk -F':' '{print $0}' passwd
$ awk -F':' '{print}' passwd
[root@i tmp]# ifconfig br0 | awk ' NR>1 {print $2}' | awk -F: 'NR<2 {print $2}'
 
取倒数第一列和倒数第二列
$ head -1 passwd |awk -F':' '{print $NF,$(NF-1)}'
/bin/bash /root
换行符(默认处理一行后才换行)
$ head -1 passwd |awk -F':' '{print $NF RS $(NF-1)}'
/bin/bash
/root
$head -1 passwd | awk 'BEGIN {FS=":"} {print $NF RS $(NF-1)}'
awk  -F: '{print "第"FNR"行" RS $1,$NF }' passwd

一次指定多个分隔符
$ awk -F':|/' '{print NF}' passwd
$ awk -F'[:/]' '{print NF}' passwd
$ ifconfig eth0|grep Bcast|awk -F':| +' '{print $4}'
$ifconfig eth0 |grep Bcast | awk -F" " '{print $2}'|awk -F":" '{print $2}'
#ifconfig br0 | grep Bcast |awk -F' | +' '{print $NF}'

定址:
 1)关键字
  BEGIN :表示在程序开始前执行
  END :表示所有文件处理完后执行
操作流程:
#/bin/awk -f
  BEGIN   {} --读前处理(读取目标文件)
  {}  --行处理
  END {} --读后处理

打印标题和结尾信息
$ awk -F':'  'BEGIN {print "user\tpasswd\thome"RS"----------------------"} ; {print $1"\t"$2"\t"$(NF-1)} ; END {print "<-----------END---------->"}' passwd
user    passwd  home
----------------------
root    x       /root
bin     x       /bin
daemon  x       /sbin
adm     x       /var/adm
lp      x       /var/spool/lpd
<-----------END---------->

 
2)正则表达式
$ awk '/root/ {print $0}' /etc/passwd  --使用普通字符定位
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

$ awk '$0 ~ /^root/ {print $0}' /etc/passwd  --使用正则表达式定位
root:x:0:0:root:/root:/bin/bash

$ awk '/^[rR]oot|^[bB]in/ {print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
# awk -F':' '/^[rR]oot|^[bB]in/ {print $1}' passwd
# awk -F: '/^[Rr][Oo][Oo][Tt]|^[Ff][tT][pP]/ {print $1}' aa  
包含ftp或者root开头的不区分大小写组合
awk  '/^[0-9]/ {print $0}' passwd           以数字开头
awk  '/^[a-zA-Z]/ {print $0}' passwd     以任意大小写字母开头
awk  '$0 ~ /^[a-zA-Z]/ {print $0}' passwd 

使用正则表达式精确定位
$ awk -F':' '$2=="" {print $0}' /etc/passwd  
$ awk -F':' '$2=="" {print $0}' /etc/shadow --查看用户中有无空密码的
$ awk -F':'  '$7 ~ /bash$/ {print $0}' /etc/passwd  -显示可以登录的用户所有信息
从第7列匹配以bash结尾,输出整行(当前行所有的列)
$awk -F: '$NF ~ /bash$/ {print $1}' /etc/passwd   显示可以登录的用户名
$ awk -F':' 'NR>=5 && NR<=10 {print $0}' /etc/passwd  显示5-10行
$ awk '/^root/,/^uucp/ {print $0}' /etc/passwd    匹配以root开头至uucp开头当前所在行
awk 'NR==2,/^uucp/ {print $0}' /etc/passwd   指定从第二行开始匹配以uucp开头,打印所有行
awk 'NR==10 , NR==20 {print $0}' /etc/passwd    打印10到20行所有内容 (等同于 awk -F':' 'NR>=10 && NR<=20 {print $0}' /etc/passwd)
awk 'NR==10 || NR==20 {print $0}' /etc/passwd   打印第10行或者第20行的所有内容
 
3)逻辑表达式
 例如:NR>40
 例如:if ( $2>50)  { print $3 }
 逻辑表达式:
   ==(等于)、!=(不等于)、>(大于)、<(小于)、>=(大于等于)、<=(小于等 于)
   ~(匹配于)和!~(不匹配于)
   !(非)、&&(与)、||(或)、和括号()
awk -F: 'NR<10 && NR>3 {print $0} ' /etc/passwd    --与
awk -F: 'NR==10 || NR==3 {print NR,$0} ' /etc/passwd   --或
awk -F: '!(NR<40) {print NR,$1}' /etc/passwd     --取反
awk -F: '$3>=500 && $3 <=60000 {print $3,$1}' /etc/passwd  --打印普通用户
awk -F: 'NR%2==0 {print NR,$0}' /etc/passwd    -- 取偶数
awk -F: 'NR%2!=0 {print NR,$0} ' /etc/passwd     --打印奇数行
awk -F: 'NR%2==1 {print NR,$0}' /etc/passwd
awk -F":" 'BEGIN {print "user_UID\tusername\t"RS"-------------------"}  ($3>=500 && $3<=60000) {print $3"\t","\t"$1}  END {print "--------------------"}' /etc/passwd
awk的流程控制
 if
 for
 while
if(expr1) action
if(expr1)action1;else aciton2
if(expr1) action1;else if(expr2);else
# awk -F: '{if($3>500) print $1,$3,"普通用户"}' /etc/passwd
# awk -F: '{if($3>500) print $1,$3,"普通用户";else print $1,$3,"不是普通用户"}' /etc/passwd
# awk -F: '{if($3==0) print $1,$3,"管理员";else if($3<500) print $1,$3,"系统用户";else print $1,$3,"普通用户"}' /etc/passwd
for
# awk 'BEGIN {for(i=0; i<=10; i++) print i}'
while
# awk 'BEGIN {i=0;while(i<=5) {print i;i++}}'
# awk 'BEGIN {i=0;while(i<=5) {print"service",i,"start";i++}}'
#循环的控制:
break  --条件满足的时候中断循环
continue  --条件满足的时候跳过循环
# awk 'BEGIN {i=0;while(i<=5) {i++;if(i==3) continue; print i}}'
# awk 'BEGIN {i=0;while(i<=5) {i++;if(i==3) break; print i}}

 
用netstat -ntl 截取所有开放的端口号
netstat -ntl |grep -v Active| grep -v Proto|awk '{print $4}'|awk -F: '{print $NF}'
netstat -ntlup |grep -Ev "Active|Proto" |awk '{print $4}' |awk -F: '{print $NF}'
netstat -tnlp | awk -F'[*/]|:+| +' 'NR>2 {print $1,$5,$(NF-2),$(NF-1)}'
 
截取权限
[root@i ~]# stat aa| grep Uid | cut -c10-13
0644
[root@i ~]# stat aa| grep Uid | awk -F':' '{print $2}' | awk -F'[(/]' '{print $2}'

[root@i ~]# stat /usr/bin/vim | grep 'Uid' | awk -F'[:(/]' '{print $3}'
 
例1:监控磁盘使用率,高于80%的找出来,输出警告,发送邮件给管理员
# df -h |grep -v Filesystem |awk '{print $1,$5}'|awk -F% '{print $1}'| awk '$2>80 {print $1"useage is over 80%,warning!!!"}' |mail -s "disk overuse problem" root
# df -h |  awk 'NR>1 {print $4"\t"$5}'  | grep %  | grep -v G | grep -v M | awk -F'%' '$1>80 {print $1"useage is over 80%,warning!!!"}' | mail -s "warring" root@localhost
# df -k |grep -v Filesystem |awk '$3/$2>0.8 {print $1"useage is over 80%,warning!!!"}' |mail -s "disk overuse problem" root
 
例2:监控CPU 15分钟内的平均负载,如果超过5则发警告邮件给管理员
uptime  |awk '$NF>5 {print "high load,warning"}' |mail -s 'xxxxx' root
 
例3:计算swap总量,使用量,剩余量,使用百分比,剩余百分比
格式要求为:
total used free used% free%
xxxxx xxxx xxxx xxx% xxx%

free |tail -1 |awk 'BEGIN {print "total\t\tused\tfree\tused%\tfree%"} {print $2"\t\t"$3"\t"$4"\t"$3/$2*100"%\t"$4/$2*100"%"}'
total           used    free    used%   free%
4096564         0       4096564 0%      100%
 
利用printf格式化输出

# awk 'BEGIN {print "hello world"}'
hello world
# awk 'BEGIN {printf "hello world"}'
hello world#
--从上面看到print和printf直接使用的主要区别就是printf不自动换行,需要使用\n来换行
# awk 'BEGIN {printf "Hello world\n" }'
Hello world
 
格式:
printf {format_expression[,argument]}
两个主要的格式说明符是s和d,s代表字符串,d表示十进制整数
                                                           
# ls -l | grep -v total | awk '{printf ("%s的大小为%d\n",$NF,$5)}' |tail
Templates的大小为4096
test的大小为25
test1的大小为9
test.sh的大小为258
test*?[].sh的大小为0
user_passwd.txt的大小为60
Videos的大小为4096
while_useradd_shift.sh的大小为100
who.out的大小为320
内部变量的大小为76

 awk -F: 'BEGIN {sum=0}  $NF=="/sbin/nologin" {printf ("%s\t",$1); sum=sum+1}  END {print "\n\n总共有:"sum"个"}' /etc/passwd
bin     daemon  adm     lp      mail    uucp    operator        games gopher   ftp     nobody  vcsa    rpc     mailnull        smmsp   nscd  ntp      oprofile        pcap    dbus    avahi   xfs     named   rpcusernfsnobody       sshd    haldaemon       gdm     avahi-autoipd   sabayonapache  squid   ais     mfs     postfix distcache       cacti
总共有:37个
 
 
1,利用awk把不允许登录的账号名打印出来(指第七列不是以/bin/bash结束的列),并统计个数
# awk -F: 'BEGIN {sum=0} $NF!~"/bin/bash" {printf ("%s ",$1);sum=sum+1} END {print "\n\n总共的个数 为:"sum}' /etc/passwd
 

2,把系统上ssh的登录日志格式化打印成类似下面的
*********************************************************
time            hostname        user    ip              port    protocol
Jul-15 15:47:20 li              root    2.2.2.35        6703    ssh2
*********************************************************
*********************************************************
time            hostname        user    ip              port    protocol
Jul-15 15:47:27 li              root    2.2.2.35        6704    ssh2
*********************************************************

# cat /var/log/secure |grep Accepted |awk '{print "***************************************************************************"}{print "time\t\thostname\tuser\tip\t\tport\tprotocol"}{print $1"-"$2,$3"\t"$4"\t\t"$9"\t"$11"\t"$13"\t"$14}{print "*************************************************************************"}'
 
# cat /var/log/secure |grep Accepted |awk ' BEGIN{print "time\t\thostname\tuser\tip\t\tport\tprotocol"}{print $1"-"$2,$3"\t"$4"\t\t"$9"\t"$11"\t"$13"\t"$14}'
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值