awk
-v设置变量
-F 指定分隔符
内置变量
FS:输入字段分隔符,默认为空白字符,读入内容的分隔符
OFS:输出字段的分隔符
RS:指定行(记录)分隔符
ORS:输出记录分隔符
NF:字段数量
NR:记录的数量
ARGC:命令行参数的个数
ARGV:数组,保存的是命令行所有的参数
例1:不依赖文件和标准输入
[root@centos7 ~]#awk ‘BEGIN{print “haha”}’
haha
BEGIN表示只处理一次,后面可以不处理文件
例2:做数值运算
[root@centos7 ~]#awk ‘BEGIN{print 2^10}’
1024
例3:打印/etc/passwd文件中的用户名和uid,输出以:号做分隔符
[root@centos7 ~]#awk -F: ‘{print $1″:”$3}’ /etc/passwd
root:0
bin:1
daemon:2
指定输入分隔符
awk -v FS=: ‘{print $1FS$3}’ /etc/passwd
FS是awk里的变量,
[root@centos7 ~]#fs=”:”;awk -v FS=$fs ‘{print $1FS$3}’ /etc/passwd
指定输入和输出分隔符
[root@centos7 ~]#fs=”:”;awk -v FS=$fs -v OFS=: ‘{print $1,$3}’ /etc/passwd
例:取分区名和利用率
[root@centos7 data]#df | grep ^/dev/sd | awk -v FS=”%” ‘{print $1}’ | awk ‘{print $1,$5}’
/dev/sda2 37
/dev/sda3 3
/dev/sda1 16
例:NF字段数量
[root@centos7 data]#awk -v FS=”:” ‘{print NF,$NF}’ /etc/passwd
7 /sbin/nologin
7 /bin/bash
7 /bin/bash
例: 打印倒数第二个字段
[root@centos7 data]#awk -v FS=”:” ‘{print $(NF-1)}’ /etc/passwd
/root
/bin
/sbin
/var/adm
/var/spool/lpd
/sbin
/sbin
/sbin
例:NR记录数量
[root@centos7 ~]#awk -v FS=”:” ‘{print NR,$1}’ /etc/passwd
1 root
2 bin
3 daemon
4 adm
5 lp
6 sync
awk -v FS=”:” ‘{print NR,$1}’ /etc/passwd /etc/fstab 假如处理的是两个文件,那么他们记录数量方式是一起编号
awk -v FS=”:” ‘{print FNR,$1}’ /etc/passwd /etc/fstab 则各自有各自的编号
例:参数的个数ARGC
[root@centos7 ~]#awk ‘{print ARGC}’ /etc/passwd /etc/inittab
3
3
3
3
例:数组ARGV
[root@centos7 ~]#awk ‘{print ARGV[1]}’ /etc/issue /etc/fstab
/etc/issue
/etc/issue
/etc/issue
/etc/issue
/etc/issue
/etc/issue
awk变量自定义变量
定义方式
1.-v var=value
[root@centos7 ~]#awk -v name=wang ‘BEGIN{print name}’
wang
2.在program中直接定义
[root@centos7 ~]#awk ‘BEGIN{name=”wang”;print name}’
wang
例:-f调用文件
[root@centos7 data]#cat scripts
{print $1,$3}
[root@centos7 data]#awk -v FS=”:” -v OFS=”=” -f /data/scripts /etc/passwd
root=0
bin=1
daemon=2
adm=3
lp=4
printf命令
格式化输出:printf “FORMAT”, item1, item2, …
(1) 必须指定FORMAT
(2) 不会自动换行,需要显式给出换行控制符,\n
(3) FORMAT中需要分别为后面每个item指定格式符
格式符:与item一一对应
%c: 显示字符的ASCII码
%d, %i: 显示十进制整数
%e, %E:显示科学计数法数值
%f:显示为浮点数
%g, %G:以科学计数法或浮点形式显示数值
%s:显示字符串
%u:无符号整数
%%: 显示%自身
修饰符:
#[.#]:第一个数字控制显示的宽度;第二个#表示小数点后精度,%3.1f
-: 左对齐(默认右对齐) %-15s
+:显示数值的正负符号 %+d
[root@centos7 data]#awk -F: ‘BEGIN{print “user uid\n———————————–“}{printf “%-20s:%10d\n”,$1,$3}END{print “———————————–“}’ /etc/passwd
模式匹配符:
~:左边是否和右边匹配包含 !~:是否不匹配
示例:
awk –F: ‘$0 ~ /root/{print $1}‘ /etc/passwd
awk ‘$0~“^root”‘ /etc/passwd
awk ‘$0 !~ /root/‘ /etc/passwd
awk –F: ‘$3==0’ /etc/passwd
例:显示用户id号大于1000小于1010的用户名和id
[root@centos7 data]#awk -F: ‘$3>=1000 && $3<=1010{print $1,$3}’ /etc/passwd
wang 1000
bash 1001
testbash 1002
basher 1003
sh 1004
nologin 1005
haha 1006
hehe 1007
aa 1008
bb 1009
feng 1010
例:取反
[root@centos7 data]#awk -F: ‘! ($3>=1000){print $1,$3}’ /etc/passwd
在awk中1为真,0为假
[root@centos7 data]#awk ‘BEGIN{print !i}’
1
[root@centos7 data]#awk ‘BEGIN{i=0;print !i}’
1
[root@centos7 data]#awk ‘BEGIN{i=2;print !i}’
0
[root@centos7 data]#awk ‘BEGIN{i=”abc”;print !i}’
0
awk控制语句if-else
语法:if(condition){statement;…}[else statement]
if(condition2){statement1}else if(condition2){statement2}else{statement3}
例:打印shell为/sbin/nologin的用户
[root@centos6 data]#awk -v FS=: ‘{if($NF == “/sbin/nologin”)print $1}’ /etc/passwd
bin
daemon
adm
lp
例2:
awk ‘BEGIN{ test=100;if(test>90){print “very good“}else if(test>60){ print “good”}else{print “no pass”}}’
awk控制语句
语法:while(condition){statement;…}
使用场景:
对一行内的各个字段逐一类似处理时使用
对数组中的各元素逐一处理时使用
例:打印某行单词,和字符长度
[root@centos6 data]#awk ‘/^[[:space:]]+kernel.*/{i=1;while(i<=NF){print $i,length($i);i++}}’ /etc/grub.conf
kernel 6
/vmlinuz-2.6.32-696.el6.x86_64 30
ro 2
root=UUID=50e87f34-5611-4315-9a53-21afd7fd859a 46
rd_NO_LUKS 10
rd_NO_LVM 9
LANG=en_US.UTF-8 16
rd_NO_MD 8
SYSFONT=latarcyrheb-sun16 25
length($i)表示变量$i字符的长度
例2:
[root@centos6 data]#awk ‘/^[[:space:]]+kernel.*/{i=1;while (i<=NF){if(length($i)>=10){print $i,length($i)};i++}}’ /etc/grub.conf
/vmlinuz-2.6.32-696.el6.x86_64 30
root=UUID=50e87f34-5611-4315-9a53-21afd7fd859a 46
rd_NO_LUKS 10
LANG=en_US.UTF-8 16
SYSFONT=latarcyrheb-sun16 25
crashkernel=auto 16
KEYBOARDTYPE=pc 15
KEYTABLE=us 11
(hd0,0)/vmlinuz-2.6.32-696.el6.x86_64 37
root=/dev/sda2 14
awk控制语句do-while循环
语法:do{statement;…}while(condition)
意义:无论真假,至少执行一次循环体
示例:
awk ‘BEGIN{ total=0;i=0;do{ total+=i;i++;}while(i<=100);print total}’
awk控制语句for循环
语法:for(expr1;expr2;expr3{statement}
例1:
[root@centos6 data]#time awk ‘BEGIN{for(i=1;i<=100000000;i++)sum=sum+i;print sum}’
5000000050000000
real 0m9.548s
user 0m9.548s
sys 0m0.003s
time命令,测试awk性能
break和continue
awk ‘BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==0)continue;sum+=i}print sum}‘
awk ‘BEGIN{sum=0;for(i=1;i<=100;i++){if(i==66)break;sum+=i}print sum}‘
next:
提前结束对本行处理而直接进入下一行处理(awk自身循环)
awk -F: ‘{if($3%2!=0) next; print $1,$3}’ /etc/passwd
[root@centos6 data]#awk -F: ‘{if($3>10 && $3<20)print $1,$3}’ /etc/passwd
operator 11
games 12
gopher 13
ftp 14
awk数组
关联数组:array[index-expression]
index-expression:
(1) 可使用任意字符串;字符串要使用双引号括起来
(2) 如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空串”,若要判断数组中是否存在某元素,要使用“index in array”格式进行遍历
若要遍历数组中的每个元素,要使用for循环
for(var in array) {for-body}
注意:var会遍历array的每个索引
例1:
[root@centos7~]#awk’BEGIN{name[“haha”]=”wang”;name[“hehe”]=”zhao”;name[“heihei”]=”zhang”;for(i in name)print name[i] }’
zhao
zhang
wang
ab -c 100 -n 2000 http://192.168.67.130/并发访问
例:
[root@centos7 ~]#netstat -tan | awk ‘/^tcp/{state[$NF]++}END{for(i in state){print i,state[i]}}’
LISTEN 9
ESTABLISHED 1
TIME_WAIT 1999
例:
[root@centos7 ~]#cat /var/log/httpd/access_log | awk ‘/^[0-9]+/{ip[$1]++}END{for (i in ip){print i,ip[i]}}’
172.20.109.152 10
192.168.67.132 4004
列:把访问量大于1000的IP放入防火墙
[root@centos7 data]#awk ‘/^[0-9]/{ip[$1]++}END{for(i in ip){if(ip[i]>1000)print i}}’ /var/log/httpd/access_log | while read ip;do iptables -A INPUT -s $ip -j REJECT;done
例:统计一个文件的单词数
[root@centos7 data]#awk ‘{for(i=1;i<=NF;i++){word[$i]++}}END{for(j in word)print j,word[j]}’ /etc/fstab
本文来自投稿,不代表Linux运维部落立场,如若转载,请注明出处:http://www.178linux.com/99070