分类: 系统运维
2014-03-06 17:55:16
以前学awk的时候没有好的习惯,不知道把一些好的例子给记录下来,等到用的时候却怎么也想不起来。
现在把这些东西都记录在博客里面。可以方便查询,也可以共享给同行们参阅。如果文章中有错误的或者有不同意见的请给我留言!
过滤IP地址的
grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}'
grep -Po '(\d+.){3}(\d+)'
jack huaxue 90
tom huaxue 70
jack shuxue 99
tom shuxue 80
要求用shell得到每个人的平均分,思路很简单,要是python的话直接dict记住总分再记住科目数,最后一除就行了。但是要求用shell,怎么办?还好awk就有关联数组的功能,因此写出如下脚本aver.awk:
awk '{if (NF == 3){if ($1 in arr){arr[$1]+=$3;cnt[$1]++}else{arr[$1]=$3;cnt[$1]=1}}}END{for (k in arr){print k "aver:"arr[k]/cnt[k]}}' a
jackaver:94.5
tomaver:75
统计访问量最大的元素
awk '{a[$10/1024" "$7" "$11]++}END{for (i in a)print a[i],i}' web.log|sort -nr -k 1|more
awk '{a[$10/1024" "$7" "$11]++}END{for (i in a)print a[i],i}' web.log|sort -nr -k 1|awk '{if ($2 > 1000) print $0}'|more
统计单个元素字节数最大的元素 (单位为 KB)
awk '{a[$10/1024" "$7" "$11]++}END{for (i in a)print a[i],i}' web.log|sort -nr -k 2|more
统计单个元素字节数为1M以上的元素的访问量 (单位为 KB)
cat |awk '{a[$10/1024" "$7" "$11]++}END{for (i in a)print a[i],i}' web.log|sort -nr -k 1|awk '{if ($2 > 1000)}'more
统计总的流量,第一个是M单位 第二个是G单位
awk '{print $10/1024}' web.log |awk '{a+=$1}END{print a/1024}'
59509.5
awk '{print $10/1024}' web.log |awk '{a+=$1}END{print a/1024/1024}'
58.1148
统计图片总流量
grep -E "jpg|gif" web.log|awk '{print $10/1024}' |awk '{a+=$1}END{print a/1024/1024}'
统计动态图片总流量
grep "gif"|awk '{print $10/1024}' |awk '{a+=$1}END{print a/1024/1024}'
http://blog.163.com/vindiesel@126/blog/static/65893019201321255822428/
我写的
awk '{if($2 in a);else{a[$2]=$0}}END{for(b in a)print a[b]}' urrfile
后来别人给出更简单的答案
awk ' !($2 in i){ i[$2]; print } ' urrfile
现在看来,还可以更简单些
awk '!a[$2]++' urrfile
awk '{print $10/1024}' web.log |awk '{a+=$1}END{print a}'
[root@kefu log_guaixun]# awk '{print $10/1024}' web.log |awk '{a+=$1}END{print a}'
6.09377e+07
[root@kefu log_guaixun]# awk '{print $10/1024}' web.log |awk '{a+=$1}END{print a/1024}'
59509.5
[root@kefu log_guaixun]# awk '{print $10/1024}' web.log |awk '{a+=$1}END{print a/1024/1024}'
58.1148
[root@kefu log_guaixun]# cat web.log |grep -E "jpg|gif"|awk '{print $10/1024}' |awk '{a+=$1}END{print a/1024/1024}'
56.8914
[root@kefu log_guaixun]# cat web.log |grep -E "gif"|awk '{print $10/1024}' |awk '{a+=$1}END{print a/1024/1024}'
cat demo_access.log |grep "28/Apr/2012"|sed -n '/03:25/,/05:30/p'
检查302状态
awk '{if($9==302)print $7,$11}'|awk -F\" '{print $1,$2}'|awk '{a[$1]++;b=$1;c[b]=$2}END{for (i in a)print a[i],i,c[b]}'|sort -nr|more
wtp 383: mac 00:27:1D:04:17:75 wlan 1 base vlan 15 wlan 5 wlan 7 base vlan 15 wlan 9 base vlan 15 wlan 10 base vlan 15
变成
wtp 383:
mac 00:27:1D:04:17:75
radio apply wlan 1 base vlan 15
radio apply wlan 5
radio apply wlan 7 base vlan 15
radio apply wlan 9 base vlan 15
radio apply wlan 10 base vlan 15
awk '{printf("%s%s\n%s%s\n",$1,$2,$3,$4);T="radio reply";split($0,a,"wlan");for(i=2;i<7;i++)print T,"wlan" a[i]}'
awk '!a[$1]++' aa
! a[$1] ++
0为假, !0 为真
以第一列(逗号分隔)为索引的数组元素的值为0则输出,输出后数组元素值++, 后面的行$1相同时a[$1]的值就不为0了。
awk '/abc/,/aaa/{print $0}' aa 意思是前面匹配abc 结尾要匹配aaa
abc 123
abs 234
aaa 234
cat a
123 343
abc 123
abs 234
aaa 234
111 121
printf 格式化处理 printf 默认不打印\n 需要自己添加
%i
%s 字符 最常用
%u
%e
%g
%f
%c
%d
控制语句 if ,while, for, case, do ... while, break, continue, next
if
[root@localhost ~]# awk -F: '{if ($3==0){printf "%-15s %s\n",$1,"administrator"}else{printf "%-15s %s\n",$1,"common-user"}}' /etc/passwd
root administrator
bin common-user
daemon common-user
awk -F: -v sum=0 '{if ($3 >= 500){sum++}}END{print sum}' /etc/passwd
4
cat /var/log/secure |awk 'BEGIN{a=0}/Fail/{a++}END{print a}'
1111
while
awk -F: '{i=1;while (i<=3) {printf "%s ",$i;i++};printf "\n"}' /etc/passwd
root x 0
bin x 1
daemon x 2
while 遍历每一个块的字符 进行条件匹配
[root@localhost ~]# cat a
89 3242 23 459
123 43 54654 2
123 345 34 67 567 67863
[root@localhost ~]# awk '{i=1; while (i<=NF){if ($i>=100)print $i; i++}}' a
3242
459
123
54654
123
345
567
67863
每一个字符长度等于3的答应出来
[root@localhost ~]#awk '{i=1; while (i<=NF){if (length($i) == 3)print $i; i++}}' a
459
123
123
345
567
do-while 至少执行一次循环体,不管满足条件与否
语法: do{statement1,statement2.....} while {condition}
awk -F: '{i=1;do{print $i;i++}while(i<=3)}' /etc/passwd
awk -F: '{i=4;do{print $i;i--}while(i<=4)}' /etc/passwd
for 循环
[root@localhost ~]# cat a
89 3242 23 459
123 43 54654 2
123 345 34 67 567 67863
[root@localhost ~]# awk '{for (i=1;i<=NF;i++){if ($i>=100)print $i}}' a
3242
459
123
54654
123
345
567
67863
for (i=1;i<=NF;i++) 逐行读取 NF
bash
array=(“mon” "tue" "wed")
关联数组
array=(a='mon' b='tue' c='wed')
array[c]
[root@localhost ~]# awk -F: '$NF!~/^$/{a[$NF]++}END{for (b in a){printf "%15s:%i\n",b,a[b]}}' /etc/passwd
/bin/sync:1
/bin/bash:1
/sbin/nologin:29
/sbin/halt:1
/sbin/shutdown:1
NF:
/bin/bash
/sbin/nologin
a[/bin/bash]
a[/sbin/nologin]
a[/bin/bash]=1
a[/sbin/nologin]=1
a[/sbin/nologin]=2
[root@localhost ~]# netstat -an|awk '/^tcp/{a[$NF]++}END{for (i in a)print i,a[i]}'
LISTEN 8
ESTABLISHED 2
next
提前结束对文本行文本处理,并接着处理下一行:例如下面的命令显示其ID号为奇数的用户
[root@localhost ~]# awk -F: '{if($3%2==0)next;print $1,$3}' /etc/passwd
bin 1
adm 3
sync 5
halt 7
news 9
awk '{a+=$1}END{print a}' b
awk的加法
awk的内置函数
length([string])
功能:取字符串长度
substr(string,start[, length])
功能:取string字符串中的字串,从start开始取,取length个;start从1开始计数
echo "123456789" | awk '{print substr($0, 5, 2)}'
56
split(string,array[,fieldsep [,seps ])
功能:将string表示的字符串以fieldsep为分隔符进行分割,并将分割后的结果保持至array为名的数组中:数组下表从0开始的序列:
netstat -an|awk '/:80\>/{split($5,clients,":");IP[clients[1]]++}END{for (i in IP)print IP[i],i}'
统计出访问80端口的 ip 访问次数
[root@baidu ~]# df -h
文件系统 容量 已用 可用 已用% 挂载点
/dev/sdb3 125G 99G 20G 84% /
/dev/sda1 99M 13M 82M 14% /boot
tmpfs 3.9G 0 3.9G 0% /dev/shm
/dev/mapper/VolGroup00-LogVol00
262G 242G 6.1G 98% /53kf
[root@baidu ~]# df -h |awk '!/^文件/{split($5,a,"%");if(a[1] > 10){print $1,$5}}'
/dev/sdb3 84%
/dev/sda1 14%
echo 123456 |awk -F '' '{for (i=1;i<=NF;i++)printf " "$i}'
1 2 3 4 5 6
awk '!/\/\*/,/\*\//' d
复制代码
取反仅仅针对/\/\*/,打印的是不匹配/\/\*/开始到匹配/\*\//结束的行,
和你想要表达的不在/* */之间的行含义不同。
这样写能实现你想要的
awk '/\/\*/,/\*\//{k=1} !k{print} {k=0}' test.txt
aaaaa
bbbbb
cccc
复制代码
[root@centos shell]# find ./ -name "init*" -ok rmdir {} \;
< rmdir ... ./init2 > ?