1. 简介
来由与做用 awk是由Aho, Weinberger, Kernighan三位大牛开发的程序,用于报告生成器,格式化文本输出,可接收标准输入
版本php
New awk(nawk)
GNU awk( gawk),centos使用的为gawk
运行原理css
分割符、域和记录linux
awk执行时,由分隔符分隔的字段(域)标记1 , 1, 0为全部域,注意:和shell中变量$符含义不一样
文件读入内存空间的每一行称为记录,文本中的一行能够为多个记录
省略action,则默认执行 print $ 0 的操做
工做原理nginx
执行BEGIN{action;… }语句块中的语句
从文件或标准输入(stdin)读取一个记录到内存空间,执行pattern{ action;… }语句块,匹配预约义的模式,若是不匹配就不处理,匹配后按照预先规定好的分隔符切割成若干字段,分割成功后,系统会对这些列分配一个域标识$ 1..$ n,直到文件所有被读取完毕。
当读至输入流末尾时,执行END{action;…}语句块web
BEGIN语句块在awk开始从输入流中读取行以前被执行,这是一个可选的语句块,好比变量初始化、打印输出表格的表头等语句一般能够写在BEGIN语句块中
END语句块在awk从输入流中读取完全部的行以后即被执行,好比打印全部行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块
pattern语句块中的通用命令是最重要的部分,也是可选的。若是没有提供pattern语句块,则默认执行{ print },即打印每个读取到的行,awk读取的每一行都会执行该语句块
2. 基本用法
格式: awk [options] var=value ‘program’ file…
选项(options):正则表达式
-v var=value: 自定义变量
-f programfile: 读取文件中的程序 awk [options] var=value -f programfile file…
-F:指明输入时用到的字段分隔符,分隔符能够指定多个sql
示例:指定[;]为记录分隔符,下例为2个记录a:b@c:d与1:2@3
1:指定[:]为字段分割符
$echo "a:b@c:d;1:2@3"|awk -v RS=";" -F":" '{print $1,$3}'
a d
1
2:指定[@:]为字段分割符
$echo "a:b@c:d;1:2@3"|awk -v RS=";" -F"[@:]" '{print $1,$3}'
a c 两个分隔符都起做用,c为第3个字段
1 3
3:以扩展正则表达式方法表示也能够
$echo "a:b@c:d;1:2@3"|awk -v RS=";" -F"@|:" '{print $1,$3}'
program 为awk本身的语法,一般是被单引号或双引号中,建议使用单引号,由于双引号在程序中会在字符串上用,避免混用shell
格式:
BEGIN语句块、可以使用模式匹配的通用语句块、END语句块,共3部分组成 ‘BEGIN{ action;… } pattern{ action;… } END{ action;… }’
经常使用格式: pattern{action statements;..}
释义pattern和action:
pattern部分决定动做语句什么时候触发及触发事件
action statements对数据进行处理,放在{ }内指明
action格式: {print|printf item1, item2, …}
要点:
逗号分隔符
输出的各item能够字符串,也能够是数值;当前记录的字段、变量或awk的表达式
如省略item,至关于print $0
示例 例如:打印出/etc/passwd文件的第1和第3行express
awk -F:
'{print $1 ,$3 }' /etc/passwd
3. awk变量
变量:分为内置和自定义变量,只要对变量赋值,就要放在选项-v的后面apache
3.1 内置变量
示例1:定义FS=’:’,在(程序)中调用变量 $awk -v FS=':' '{print $1,FS,$3}’ /etc/passwd named:25
示例2:一次引用多个变量,中间须要使用逗号隔开 $awk -v FS=: '{print $1FS,FS,FS$3}' /etc/passwd named: : :25
示例3:还能够引用shell中的变量,先声明fs=:,而后用awk调用 $fs=:;awk -v FS="$fs" '{print $1FS$3}' /etc/passwd named:25
OFS(output field separator):指定输出字段分隔符,默认为空白字符
示例:以###做为字段分隔符 $awk -F":" -v OFS=### '{print $1,$3,$2}' /etc/passwd named###25###x
RS(record separator):输入记录分隔符,指定输入时的换行符
示例:建立文本,以下awk.txt所示,[@,!,?]与[1,2,3,4]以及[A,B,C\naa,bb,cc],以[;]分隔开
1. 建立实验文本
$cat awk.txt
@,!,?;1,2,3,4;A,B,C
aa,bb,cc
2. 指定输入字段分隔符为[,],输出字段分隔符为[==],输入记录分隔符为[;]
$awk -v FS="," -v OFS="==" -v RS=";" '{print $3,$4}' awk.txt
?== <==第一个记录@,!,?没有第4个字段
3==4 <==第二个记录1,2,3,4,显示后两个
C <==第三个记录,保留原有格式换行,C\naa为第三个字段
aa==bb
ORS:输出记录分隔符,输出时用指定符号代替换行符
承上例,每条记录输出时默认为换行处理,能够经过ORS指定
$awk -v FS="," -v OFS="==" -v RS=";" -v ORS="***" '{print $3,$4}' awk.txt
?==***3==4***C <==记录输出时以指定的符号代替原回车换行
aa==bb***
NF:字段数量
$awk -F: '{print NF}' /etc/passwd
7 <==统计字段数量
$awk -F: '{print $(NF-6)}' /etc/passwd
named <==显示第一列内容,至关于$1,要用括号括起来
NR:记录号
$awk -F: '{print NR,$1}' /etc/passwd
45 named <==至关于多了个行号
FNR:各文件分别计数,记录号
$awk -F: '{print NR,$1}' /etc/passwd /etc/group
121 named <==一共有多少记录
处理多个文件时,使用NR会将记录号累计,不会按文件分开,这时须要使用FNR
$awk -F: '{print FNR,$1}' /etc/passwd /etc/group
45 named <==/etc/passwd文件最后一个记录
76 named <==/etc/group文件最后一个记录
FILENAME:当前文件名 承上例,若是以为显示不清楚,能够加上文件名
$awk -F: '{print FNR,FILENAME,$1}' /etc/passwd /etc/group
76 /etc/group named
ARGC:命令行参数的个数
$awk '{print ARGC}' /etc/passwd /etc/group
3 <==统计命令行参数的个数
ARGV:数组,保存的是命令行所给定的各参数 上例为何是3个参数?使用ARGV查看各参数
$awk '{print ARGV[0] }' /etc/passwd /etc/group
awk <==将awk算为了一个参数
$awk '{print ARGV[2] }' /etc/passwd /etc/group
/etc/group <==第三个参数
3.2 自定义变量(区分字符大小写)
格式
-v var=value 例如 -v NAME=USERNAME
直接在程序中定义变量{NAME=USERNAME;print…}
示例
示例:使用格式1自定义
$awk -F: -v USER=“username” -v UID=“userid” ‘{print USER":"$1,UID":"$3}’ /etc/passwd /etc/group
username:named userid:25 这样显示不是很清晰,还记得记录分隔符吗
$awk -F: -v USER=“username” -v UID=“userid” -v ORS="\n------\n" ‘{print USER":"$1"\n"UID":"$3}’ /etc/passwd /etc/group
username:screen userid:84
username:named userid:25
示例:使用格式2自定义
$awk -F: -v ORS="\n------\n" '{USER="username"; UID="userid"; print USER":"$1"\n"UID":"$3}' /etc/passwd /etc/group
示例:将action放入文件,使用-f选项
1. 将程序内容放入文件awk2.txt 中
$cat awk2.txt
{USER="username"; UID="userid"; print USER":"$1"\n"UID":"$3}
2. 执行如下命令,写入文件的程序就不须要单引号了
$awk -F: -v ORS="\n------\n" -f awk2.txt /etc/passwd
4. action中的printf命令
格式 printf “FORMAT”, item1, item2, …
注意事项
必须指定FORMAT
不会自动换行,须要显式给出换行控制符,\n
FORMAT中须要分别为后面每一个item指定格式符
格式符:与item对应
符号
释义
%c
显示字符的ASCII码
%d, %i
显示十进制整数
%c
显示字符的ASCII码
%e, %E
显示科学计数法数值
%g, %G
以科学计数法或浮点形式显示数值
%s
显示字符串
%u
无符号整数
%%
显示%自身
#[.#]:第一个数字控制显示的宽度;第二个#表示小数点后精度,如%3.1f
-: 左对齐(默认右对齐),如%-15s
+:显示数值的正负符号,如%+d
示例
示例1: 取出/etc/passwd第1,3行,并在其前分别加Username和UID
awk -F: ‘{
printf "Username: %- 15s,UID:%d \n" ,
$1 ,
$3 }’ /etc/passwd
示例2:%s对应$ 1,表示文件第一行为字符串,在%与s中间能够添加参数[-]表示左对齐[20]表示第一列所占宽度,同理%-4d表示$2占4个字符宽度左对齐
$awk -F:
'{printf"|%-20s %-4d|\n---------------------------\n",$1,$3 }' /etc/passwd
示例3:在这里演示一下BEGIN的效果,添加表头,效果以下
$awk -F:
'BEGIN{print "|user |ID |\n----------------------------"}' '{printf"|%-20s |%-4d|\n----------------------------\n",$1,$3 }' /etc/passwd
示例4:小数处理示例
1 :
$echo "3.1415 1.15926" |awk
'{printf "%2.2f;%1.4f",$1,$2}'
3.14 ;
1.1593
%2 .
2 f第一个
2 表示宽度,第二个
2 个小数点保留位数
%1 .
4 f最后一位达到
6 时会进位
2 :
$echo "3.1415 1.15925" |awk
'{printf "%2.2f;%1.4f",$1,$2}'
3.14 ;
1.1592
%1 .
4 f最后一位值为
5 时不会进位
3 :
$echo "3.1415 11.15925" |awk
'{printf "%2.2f;%10.4f",$1,$2}'
3.14 ;
** *11 .
1593 <==这里为了显示效果,以
** *代 替空格,共
10 个宽度
%10 .
4 f宽度起做用了,说明宽度若是小于实际占用值,会以实际宽度为准
5. 操做符
5.1 算术操做符:
操做符
定义
+
加
-
减
*
乘
/
除
%
取余
^
幂
-x
转换为负数
+x
转换为数值
5.2 赋值操做符:
操做符
定义
=
赋值
+=
将加的结果赋给变量
-=
将减的结果赋给变量
*=
将乘的结果赋给变量
/=
将除的结果赋给变量
%=
将取余的结果赋给变量
^=
将取幂的结果赋给变量
++
变量加1
–
变量减1
示例:下面两语句有何不一样 awk ‘BEGIN{i=0;print ++i,i}’ awk ‘BEGIN{i=0;print i++,i}’
[root
@hai7 ~]
$awk 'BEGIN{i=10;print ++i,i}'
11 11
先递增,再将递增值打印
[root
@hai7 ~]
$awk 'BEGIN{i=10;print i++,i}'
10 11
先打印i值,再递增
5.4 比较操做符:
操做符
定义
==
等于
!=
不等于
>
大于
>=
大于等于
<
小于
<=
小于等于
5.5 模式匹配符
操做符
定义
~
左边是否和右边匹配
!~
是否不匹配
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1 :筛选文件/etc/passwd中包含root的行
[root
@hai7 ~]
$awk -
F : '$0 ~ /root/{print NR$1}' /etc/passwd
1 root
10 operator
2 :筛选文件/etc/passwd中以root开头的行
[root
@hai7 ~]
$awk -
F : '$0 ~ "^root"{print NR,$1}' /etc/passwd
1 root
3 :筛选文件/etc/passwd中不包含root的行
[root
@hai7 ~]
$awk -
F : '$0 !~ /root/{print NR,$1}' /etc/passwd
2 bin
9 mail
11 games
4 :筛选第三字段为
0 的行
[root
@hai7 ~]
$awk -
F : '$3==0' /etc/passwd
root: x: 0 : 0 :root :/root :/bin/bash
5.6 逻辑操做符:与&&,或||,非!
1 :筛选第 3 个字段大于等于 50 而且小于等于 60 的行 [root@hai7 ~] $awk -F: ' $3 >= 50 && $3 <= 60 {print NR, $1} ' /etc/passwd 31 tss 2 :筛选第 3 个字段等于 0 或大于等于 1000 的行 [root@hai7 ~] $awk -F: ' $3 == 0 || $3 >= 1000 {print NR, $1} ' /etc/passwd 1 root 29 nfsnobody 43 dong 3 :筛选第 3 个字段小于等于 1000 之外的行 $awk -F: '!( $3 <= 1000 ) {print NR, $1} ' /etc/passwd 29 nfsnobody
先定义条件第
3 字段大于等于
1000 ,若是成立则打印
type ="user" ,不成立打印
type ="sys"
[root@hai7 ~]$awk -F: '{$
3 >=
1000 ?
type ="user" :
type ="sys" ;printf
"%+15s %s\n" ,$
1 ,
type }' /etc /passwd
root sys
nfsnobody user
6 awk-PATTERN
若是未指定:空模式,匹配每一行
/regular expression/:仅处理可以模式匹配到的行,须要用/ /括起来
例1:判断磁盘利用率,取出设备行
$df|awk -F " +|%" '/^\/dev\/sd/{print $1,$5}'
/dev/sda2 11
/dev/sda3 1
/dev/sda1 16
例2:统计磁盘文件系统类型
$awk -F" +" '/^UUID/{print $3}' /etc/fstab|sort|uniq -c
2 swap
3 xfs
relational expression: 关系表达式,结果为“真”才会被处理
真:结果为非0值,非空字符串
假:结果为空字符串或0值
示例
空格或者非0数值,返回值为非空,结果都为真,能够打印结果 awk -F: '" "{print $1}' /etc/passwd
awk -F: '1{print $1}' /etc/passwd
awk ‘!0’ /etc/passwd
空值或者0,返回值为空,结果为假,不作处理 awk -F: ' ""{print $1} ' /etc/passwd
awk -F: '0{print $1}' /etc/passwd
awk ‘!12345’ /etc/passwd
任何非0值取反都为空
下例分为两条命令
[root@hai7 ~]$awk -F: 'i=1;j=1{print i,j}' /etc/passwd
named:x:25:25:Named:/var/named:/sbin/nologin
1 1
i=1;j=1{print i,j}是两条命令
i=1省略了{print ...}因此默认打印$0
seq 10 |awk ‘i=0’
取偶数行或奇数行 打印奇数行,由于i没有指定值因此为空,第一次执行时为空=!空,因此打印1,第二次执行时,非空=!非空值为0,因此不处理,以此类推,能够经过seq 10 | awk '{i=!i;print i}'
查看返回结果
seq 10 |awk 'i=1'
打印全部数字
seq 10 | awk 'i=!i'
打印奇数行
seq 10 | awk '!(i=!i)'
打印偶数行
seq 10 |awk -v i=1 'i=!i'
打印偶数行
line ranges:行范围
利用正则表达式写法取范围 startline,endline:/pat1/,/pat2/ 不支持直接给出数字格式 awk -F: ‘/^root\>/,/^nobody\>/{print $1}' /etc/passwd
先要处理指定的行范围,能够利用NR记录编号来实现 awk -F: '(NR>=10&&NR<=20){print NR,$1}' /etc/passwd
BEGIN/END模式 BEGIN{}: 仅在开始处理文件中的文本以前执行一次 END{}:仅在文本处理完成以后执行一次
1
2
3
4
5
6
7
8
9
10
11
12
13
示例1:
[root@hai7 ~]$awk -F : 'BEGIN {print "USER USERID"} {print $1":"$3} END{print "end file"}' /etc/passwd
USER USERID <==BEGIN的内容
root:0
apache:48
named:25
end file <==END的内容
示例2:
$awk -F: '{print "USER USERID";print $1":"$3} END{print "end file"}' /etc/passwd
USER USERI <==不是开始处理的文本,会被循环打印
root:0
USER USERI
bin:1
7. awk action
7.1awk控制语句if-else
语法 if(condition){statement;…}[else statement] if(condition1){statement1}else if(condition2){statement2}else{statement3}
使用场景:对awk取得的整行或某个字段作条件判断
示例:
示例1:取出第3字段大于等于1000的行
awk -F:
'{if($3 >=1000)print $1 ,$3 }' /etc/passwd
awk -F:
'$3 >=1000{print $1 ,$3 }' /etc/passwd
效果相同,格式不一样控制语句是action里的要写在花括号内,判断语句是属于patter的要写在花括号外面
示例2:取磁盘利用率高于5%的
$df|awk -F
" +|%" '/^\/dev\/sd/{
if ($
5 >
5 ){print $
1 ,$
5 ;print
"it is full" }}'
/dev/sda2
11
it is full
/dev/sda1
16
it is full
示例3:取访问日志中IP地址重复次数超过100的,放到防火墙中
[root
@hai7 ~]
$ab -c1
0 -n
100 http:
// 172.20 .
50.201 / 实验准备屡次访问某地址
[root
@hai7 ~]
$cat /var/
log /httpd/access_log|awk -F
" " '{print $1}' |uniq -c|awk -F
" " '{if($1>100){print $2}' |
while read ip;
do iptables -A INPUT -
s $ip -j REJECT;done
[root
@hai7 ~]
$iptables -F 清空防火墙
示例3:shell类型使用bash的行
awk -F:
'{if($NF =="/bin/bash") print $1 }' /etc/passwd
示例4:第3字段大于等于1000的标记为Common user,不然标记为root or Sysuser
awk -F: '{if(
$3 >=1000) {printf
"Common user: %s\n" ,
$1 } else {printf
"root or Sysuser: %s\n" ,
$1 }}' /etc/passwd
awk -F: '{if(
$3 >=1000) printf
"Common user: %s\n" ,
$1 ; else printf
"root or Sysuser: %s\n" ,
$1 }' /etc/passwd
7.2 awk控制语句 while循环
语法: while(condition){statement;…}
条件“真”,进入循环;条件“假”,退出循环
使用场景: 对一行内的多个字段逐一相似处理时使用 对数组中的各元素逐一处理时使用
示例:
示例1:用awk写1..100相加
$awk 'BEGIN{sum=0;i=1;while(i<=100){sum+=i;i++};print sum}'
5050
示例2:找出无论前面多少空格linux16开头的行,统计各字段字符串长度
[root
@hai7 ~]awk
'/^[[:space:]]*linux16/{i=1;while(i<=NF){print $i,length($i); i++}}' /etc/grub2.cfg
示例中
length 是系统函数,用来统计括号中字符串长
[root
@hai7 ~]
$awk 'BEGIN{print length("sdgdgasdfwergejut")}'
17
示例3:统计字段字符串长度超过10的
awk '/^[[:
space :]]*linux16/{i=
1 ;
while (i<=NF) {
if (
length ($i)>=
10 ) {print $i,
length ($i)}; i++}}' /etc/grub2.cfg
示例4:判断随机数最大值与最小值
1 :生成以逗号为分隔符的随机数到文件f1
[root@hai7 ~] $(echo
"$RANDOM" ;
for ((i=
1 ;i<
100 ;i++));
do echo -n
",$RANDOM" ;done)>f1
2 : 取出随机数最大值和最小值
[root@hai7 ~] $awk -
F' ,
' ' {max=$
1 ;
min =$
1 ;i=
2 ;while(i<=NF){
if ($i>max){max=$i}
else if ($i<
min ){
min =$i};i++;}}END{print
"max=" max,
"min=" min }
' f1 max=32377 min=148 3:判断结果是否正确 [root@hai7 ~]tr ' ,
' ' \
n' <
f1. txt|shot -nr
7.3 控制语句 do-while循环
语法 do {statement;…}while(condition)
意义 不管真假,至少执行一次循环体
示例:
示例1:1..100相加
$awk 'BEGIN{sum=
0 ;i=
1 ;
do {sum+=i;i++}
while (i<=
100 );print sum}
示例2:统计linux16行,大于10个字符的字段
$awk '/^[[:space:]]*linux16/{i=
1 ;
do {
if (
length ($i)>=
10 ){print $i,
length ($i)}; i++}
while (i<=NF)}' /etc/grub2.cfg
7.4 awk控制语句 for循环
语法 for(expr1;expr2;expr3) {statement;…}
常见用法: for(variable assignment;condition;iteration process){for-body}
特殊用法:可以遍历数组中的元素 - 语法:for(var in array) {for-body}
示例:
示例1:统计linux16行,各字段字符长度,
awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i ,length($i )}}' /etc/grub2.cfg
示例2:从1+到100相加
awk
'BEGIN{sum=0;for(i=1;i<=100;i++)sum+=i;print sum}'
7.5 awk控制语句 switch语句
语法: swich定义的表达式,是否为case后的只或者正则表达式,若是是则执行statement1, 若是不匹配则继续判断第二个case后的值是否匹配,匹配则执行statement2,都不匹配则执行default后续。
格式 switch(expression) {case VALUE1 or /REGEXP/: statement1; case VALUE2 or /REGEXP2/: statement2; …; default: statementn}
7.6 awk控制语句 break、continue及next
[root@hai7 /etc/selinux]$awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i==50)break;sum+=i} ;print sum}'
1225
循环到50,就不日后加了
continue [n]结束单次循环
1 :i
%2 ==
1 意思为奇数循环,跳过奇数循环,得偶数总和
[root
@hai7 /etc/selinux]
$awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==1)continue;sum+=i} ;print sum}'
2550
2 :结束第
50 次循环,会继续进行后续循环
[root
@hai7 /etc/selinux]
$awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i==50)continue;sum+=i} ;print sum}'
5000
next: 提早结束对本行处理而直接进入下一行处理(awk自身循环)
打印 奇数行 awk -F: '{if( $3 % 2 != 0 )next;print NR, $1 , $3} ' /etc/passwd
8. 性能比较
使用awk、shell、bc计算100000相加,参考所用时间,判断工做性能 一、awk for循环
[root
@hai7 /etc/selinux]
$time awk
'BEGIN{sum=0;for(i=1;i<=100000;i++)sum+=i ;print sum}'
5000050000
real 0m
0 .
011 s
user 0m
0 .
010 s
sys 0m
0 .
001 s
二、awk while循环
2. $
time awk 'BEGIN{sum=
0 ;i=
1 ;
while (i<=
100 ){sum+=i;i++};print sum}'
5050
real 0 m0
.003 s
user
0 m0
.002 s
sys
0 m0
.001 s
三、shell for循环
$time for ((sum=
0 ,i=
1 ;i<=
100000 ;i++));
do let sum+=i;
done ;
echo $sum
real
0 m0.
666 s
user
0 m0.
666 s
sys
0 m0.
000 s
四、shell while循环
$time ( sum=
0 ;i=
1 ;
while [
$i -le
100000 ] ;
do let sum+=i;
let i++;
done ;
echo $sum )
5000050000
real
0 m1.
064 s
user
0 m0.
992 s
sys
0 m0.
072 s
五、bc计算
$time seq
-s +
100000 |bc
5000050000
real
0 m0.
041 s
user
0 m0.
036 s
sys
0 m0.
007 s
9. awk数组
9.1 awk支持关联数组
arr[“key”]=value 键值对,每一个键后面对应着相应的值, 当按下相应的键时, 就会输出相应的结果
格式 array[index-expression]
index-expression:
可以使用任意字符串;字符串要使用双引号括起来
若是某数组元素事先不存在,在引用时,awk会自动建立此元素,并将其值初始化为“空串”
若要遍历数组中的每一个元素,要使用for循环,格式为for(var in array) {for-body}
示例
•awk ‘!arr[0 ] + + ′ d u p f i l e 去 掉 重 复 行 , 例 如 文 件 内 容 为 0]++′dupfile去掉重复行,例如文件内容为 cat f2 abc cvb abc 当awk读入第一行时,arr的下标为abc,没有赋值为空,取反为非空,因此打印第一行,arr[abc]=1 读入第二行是,arr的下标为cbv,没有赋值为空,取反为非空,因此打印 读入第三行时,arr的下标为abc,值为1,取反为空,因此不打印 arr[abc]=2
去掉重复行还可使用sort -u f2 •awk ‘{!arr[0 ] + + ; p r i n t 0]++;print 0, arr[$0]}’ dupfile
分别定义数组weekdays的键值对为[“mon”]=”Monday”,[“tue”]=”Tuesday”,经过for来遍历
awk 'BEGIN{weekdays[
"mon" ]=
"Monday" ;weekdays[
"tue" ]=
"Tuesday" ;
for (i
in weekdays) {print weekdays[i]}}'
统计tcp状态,NF表明最后一个字段,i表示值,state[i]表示累计结果
netstat -
tan | awk '/^tcp/{state[$NF]++}END{
for (i
in state) { print i,state[i]}}'
统计IP访问次数,f1为导出的IP访问日志格式为,默认以空格为分隔符 172.20.7.53 - - [10/Sep/2018:10:18:53 +0800] “GET / HTTP/1.0” 403 4961 “-” “ApacheBench/2.3”
awk '{ip[$1]++}
END {for (i in ip){print ip[i],i}}' f1|sort -rn
分别统计男生女生的平
[root
@hai7 /data]$cat f2
name grade boyorgirls
A
76 G
B
98 M
C
66 M
D
95 G
E
86 G
F
79 M
[root
@hai7 /data]$awk '!/ ^name/{
if ($
3 ==
"M" ){score_m+=$
2 ;number_m++}
else {score_g+=$
2 ;number_g++}}END{
print "avg_m=" score_m/number_m
"" ,
"avg_g=" score_g/number_g}
' f2 avg_m=81 avg_g=85.6667
方法二
[root
@hai7 /data]
$awk 'NR!=1{score[$3]+=$2;num[$3]++}END{for(sex in num){print sex":avg="score[sex]/num[sex]}}' f2
G :avg= 85.6667
M :avg= 81
9.2 自定义函数
格式: function name ( parameter, parameter, … ) { statements return expression }
示例:
cat fun.awk
function max (v1,v2) {
v1>v2?
var =v1:
var =v2
return var
}
BEGIN{a=
3 ;b=
2 ;
print max(a,b)}
awk –f fun.awk
3
9.3 awk中调用shell命令
空格是awk中的字符串链接符,若是system中须要使用awk中的变量可使用空格分隔,或者说除了awk的变量外其余一概用”“引用起来。
格式 system(“$var”)
示例 awk BEGIN'{system("hostname") }'
awk 'BEGIN{score=100; system("echo your score is " score) }'
9.4 awk脚本
将awk程序写成脚本,直接调用或执行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1 :将pattern{action statements;..}写到文本中
[root
@hai7 /data]
$cat f3
{
if (
$3 >=
1000 )
print $1 ,
$3 }
2 :调用文原本筛选文件
$awk -F: -f f3 /etc/passwd
nfsnobody
65534
v9
1000
3 :创建awk执行脚本
$cat f3
{
if (
$3 >=
1000 )
print $1 ,
$3 } <==pattern{action statements;..}
4 :加执行权限
chmod +
x f3
5 :调用脚原本过滤文本
./f3 –F:
/etc/passwd
9.4.1 向awk脚本传递参数
格式 awkfile var=value var2=value2… Inputfile
注意事项
在BEGIN过程当中不可用。直到首行输入完成之后,变量才可用。
能够经过-v 参数,让awk在执行BEGIN以前获得变量的值。命令行中每个指定的变量都须要一个-v参数
示例
1 :编辑awk脚本
cat test.awk
#!/bin/awk –f
{
if (
$3 >=
min &&
$3 <=
max )
print $1 ,
$3 }
2 :加执行权限
chmod +x test.awk
3 :执行脚本,向脚本传递变量以下,也可使用-v
min =
100 ,每一个变量前都要加-v
./test.awk -F:
min =
100 max =
200 /etc/passwd
10. awk数值处理
用:作分隔符将
2008 :
08 :
08 08 :
009 :
09 分割为
5 段,分别存放在下标为
1 的
str [
1 ]=
2008 ,
str [
2 ]=
08 ...
echo
"2008:08:08 08:009:09" |awk
'{split($0,str,":")}END{for(i in str)print i,str[i]}'
4 009
5 09
1 2008
2 08
3 08 08
<link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-7f770a53f2.css" rel="stylesheet">
</div>