文本三剑客之一 AWK

文本三剑客之一

awk ‘BEGIN{print “hello”}` 执行第一步不读取文件。只打印hello

awk -F: ‘{print $1,$3}’ /etc/passwd

读取/etc/passwd 以-F :为分隔符 打印 $1,$3 以空格隔开

df |awk ‘{print $1,$5}’

读取df命令,因为分隔符是空格所有不用指定,打印的1列的第5列

################################################################################################################

AWK支持变量,分为内部变量和自定义变量

内部变量

列的分隔符

FS 是输入的变量

例: awk -v FS=: ‘{print $1,$2}’ /etc/passwd 以空格为分隔符

例: awk -v FS=: ‘{print $1FS$2}’ /etc/passwd 调用命令以变量FS的:为分隔符

OFS 为输出的分隔符

例: awk -v FS=: -v OFS=: ‘{print $1F,$2}’ /etc/passwd 以OSF指定的:为分隔符

RS行的分隔符

例: awk -v RS=” ” ‘{print $1,$2}’ /etc/passwd 以变量RS定义的空格为分隔符,打印第一行和第二行

例: awk -v ORS=”===” ‘{print}’ /etc/passwd 以变量ORS定义的输出===为分隔符

NF 查看以分隔符隔开的字段有几个

例:awk -v FS=”:” ‘{print NF}’ /etc/passwd

$NF 显示最后一个字段

例:awk -v FS=”:” ‘{print $NF}’ /etc/passwd

$(NF-1) 显示倒数第2个字段

例:awk -v FS=”:” ‘{print $(NF-1)}’ /etc/passwd

例:ls /mnt/cdrom/Packages/ |awk -v FS=”.” ‘{print $(NF-1)}’ |sort |uniq -c

NR 加编号,如果有多个文件,默认编号加一起

例: awk -v FS=”:” ‘{print NR,$0}’ /etc/passwd 给每一行的行首加一个编号

FNR 如果有多个文件,分开加编号

例:awk -v FS=”:” ‘{print FNR,$0}’ /etc/passwd /etc/fstab

FILENAME 在输出的结果前叫文件名字

例:awk -v FS=”:” ‘{print FILENAME,$0}’ /etc/passwd /etc/fstab

**********************************************************************************************************************

自定义变量

awk -v test=”hello,wak” ‘{print test,$1}’ /etc/passwd

自定义一个test的变量 在文件的每一行前加变量

awk -v test=”hello,wak” ‘BEGIN{print test}’

BEGIN 不执行文件,只执行第一次

awk ‘BEGIN{test=”hello.awk”;print test}’

awk -v FS=: -v OFS=: ‘{var=”name”;print var,$1}’ /etc/passwd

##########################################################################################################################3###########################3

printf

printf不会自动换行得加\n

awk -F: ‘BEGIN{print “user uid\n——————————–“}{printf “%-20s:%10d\n”,$1,$2}’ /etc/passwd

打印文件的第1列和第3列,

第一列%-20s -字符靠左。后面有20个空格

中间用:分隔

第3例%10d默认靠右,字符前面有10个空格

printf不会自动换行得加\n

BEGIN 打印表头

第一列的表头是user ,第三列的表头是uid

\n——————————– 在下一行显示-

做一个列表

#!/bin/bash

#

#********************************************************************

#Author: zhouyafei

#Date: 2018-05-10

#FileName: s1.sh

#Description: The test script

#Copyright (C): 2018 All rights reserved

#********************************************************************

#%-5s,-是左对齐,左对齐宽度为5的字符串 ,如果不加-默认右对齐

#%-4.2f:.2是保留两位小数点

# \n 是换行符

printf “%-5s %-10s %-4s\n” NO Name Mark

printf “%-5s %-10s %-4.2f\n” 1 Sarath 80.3456

printf “%-5s %-10s %-4.2f\n” 2 James 90.787687

printf “%-5s %-10s %-4.2f\n” 3 Sarath 70.09987

awk ‘BEGIN{i=0;print ++i,i}’

++i是先相加在执行print打印 结果是 1 1

awk ‘BEGIN{i=0;print i++,i}’

i++ 先执行print打印i的值,在相加 。结果是0 1

#########################################################################################################################

操作符 左边是否和右边符合

格式是 $0 ~ / /

awk -F: ‘$0 ~ /root/{print $0}’ /etc/passwd

-F: 以:为分隔符

$0 ~ /root/ 显示包含root的行

{print $0} 一行全部显示

awk ‘$0 ~ /^root/’ /etc/passwd

代表默认打印{print $0}

awk -F: ‘$0 !~ /root/{print $0}’ /etc/passwd

$0 !~ /root/ 显示不包含root的行

{print $0} 一行全部显示

awk -F: ‘$0 ~ /^root/{print $0}’ /etc/passwd

/^root/显示以root开头的行 ^在正则表达式中的意思是开头 $在正则表达式的意思是行尾

{print $0} 一行全部显示

df -h |awk -v FS=” ” ‘$0 ~ /^\/dev\/sd/{print $1,$5}’

-v FS=” ” 代表分隔符为空格,也可以用-F“ ”代表,也可以不写

$0 ~ /^\/dev\/sd/ 代表/dev/da开同的行 ,因为是正则表达式所有得加转义符,转到原来的意思

{print $1,$5} 代表现在第一列和第五列

#####################################################################################################################################################

可以显示大于多少,小于多少 ,等于多少,大于等于多少,小于等于多少

df -h |awk -v FS=”%” ‘$0 ~ /^\/dev\/sd/{print $1}’ |awk ‘$5>=10’

-v FS=”%” 以百分号为分隔符

$0 ~ /^\/dev\/sd/代表/dev/da开同的行 ,因为是正则表达式所有得加转义符,转到原来的意思

{print $1} 显示以百分号为分隔符,以/dev/da开头的行

$5>=10 $5显示第5列 大于等于10的行

df -h |awk -v FS=”%” ‘$0 ~ /^\/dev\/sd/{print $1}’ |awk ‘$5>=10{print $1,$5}’

awk -F: ‘$3>=1000 && $3<=1010’ /etc/passwd

-F: 以:为分隔符

$3>=1000 第三列大于等于1000

&& 代表和

$3<=1010 第三列小于等于1010

取反

awk -F: ‘ ! ($3>=1000) ‘ /etc/passwd

‘ ! ($3>=1000) ‘ 显示不是大于等于1000的数字

awk ‘BEGIN{print 1+1}’ 相加

awk ‘BEGIN{print i}’ :i的值为空

awk ‘BEGIN{print !i}’ :i的值取反为1

[root@centos7 ~]#awk ‘BEGIN{i=0;print !i}’ :i有值为0 取反为1

1

[root@centos7 ~]#awk ‘BEGIN{i=1;print !i}’ :i有值为1 取反为0

0

[root@centos7 ~]#awk ‘BEGIN{i=”abc”;print !i}’

0

[root@centos7 ~]#awk ‘BEGIN{i=””;print !i}’

1

在AWK中发现一旦没有值或空值,取反都为1

在AWK中通常认为0位假,1位真

###########################################################################################################################################

条件表达式(三目表达式)

三目表达式就是三个组合在一起

selector?if-true-expression:if-false-expression

如果selector结果是真就执行if-true-expression,反之就执行if-false-expression

例:

awk -F: ‘{$3>=1000?usertype=”Common User”:usertype=”Sysadmin or SysUser”;printf “%-20s:%-s\n”,$1,usertype}’ /etc/passwd

usertype=”Common User” 定义变量

usertype=”Sysadmin or SysUser” 定义变量

如果$3>=1000就执行usertype=”Common User”

如果不是$3>=1000就执行usertype=”Sysadmin or SysUser”

printf 格式字符输出

– 是左对齐

“%-20s代表左对齐,宽度是20个字符

:是分隔符

%-s 左对齐

\n 回车,printf默认不会换行

$1,usertype 显示文件的第一列和变量usertype

##########################################################################################################################################33

正则表达式

awk -F: ‘/^r/{print $1}’ /etc/passwd

以r开头的行显示第一列,以-F :为分隔符

df -h |awk ‘/^\/dev\/sd/{print $1,$5}’

/^\/dev\/sd/ 显示以/dev/sd开头的行

{print $1,$5} 显示第一列和第五列

cat /etc/fstab |awk ‘/^#/’

显示文件以#号开头的行

cat /etc/fstab |awk ‘!/^#/’

‘!/^#/’ 取反

显示不以#开头的行

cat /etc/httpd/conf/httpd.conf |awk ‘!/^ *#/’

‘!/^ *#/’显示不以空格和#号开头的行

awk -F: ‘/\/bin\/bash$/{print $1,$NF}’ /etc/passwd

/\/bin\/bash$/ 显示以/bin/bash 结尾的行

$NF 代表最后一个字段

awk -F: ‘$NF == “/bin/bash”{print $1,$NF}’ /etc/passwd

awk -F: ‘/^root\>/,/^nobody\>/{print $1}’ /etc/passwd

显示以:为分隔符,以root开头到nobody开头的行,只显示第一列

-F: 为分隔符

/^root\>/ root开头 单词锚定

/^nobody\> nobody开头 单词锚定

{print $1} 第一列

awk -F: ‘(NR>=10&&NR<=20){print NR,$1}’ /etc/passwd

给文件的从第10行到第20行加行号

NR代表第几行

(NR>=10&&NR<=20) 代表大于等于10行 小于等于20的行

{print NR,$1} NR代表10到20之间的数字 ,数字后面跟文件的第一列

awk -F: ‘BEGIN{print “USER USERID”}{print $1,$3}END{print “end file”}’ /etc/passwd

打印文件的第一列和第三列 ,在每列的开头添加表同,在结尾添加end file

BEGIN{print “USER USERID”}打印表头 USER和USERID

{print $1,$3} 显示第一列和第三列

END{print “end file”} 在结尾添加end file

0或者空为假不显示

不为空和有值1为真

seq 10 |awk ‘i=0’ i等于0 为假 不显示

seq 10 |awk ‘i=1’ i等于1 为真 显示信息

打印奇数行

[root@centos7 ~]#seq 10 |awk ‘i=!i’ i的值为0 取反为1 所以打印1

1 i的值变成了1 ,取反为0假 所以2不打印

3 i的值变成了0 ,取反为1真 所以打印3

5 i的值变成了1 ,取反为0假 所以4不打印

7 i的值变成了0 ,取反为1真 所以打印5

9 i的值变成了1 ,取反为0假 所以6不打印

i的值变成了0 ,取反为1真 所以打印7

i的值变成了1 ,取反为0假 所以8不打印

i的值变成了0 ,取反为1真 所以打印9

i的值变成了1 ,取反为0假 所以10不打印

[root@centos7 ~]#seq 10 |sed -n ‘1~2p’ 用sed打印奇数行

1

3

5

7

9

打印偶数行

[root@centos7 ~]#seq 10 |awk ‘!(i=!i)’

2

4

6

8

10

[root@centos7 ~]#seq 10 |awk -v i=1 ‘i=!i’ 直接给i赋值为1

2

4

6

8

10

[root@centos7 ~]#seq 10 |sed -n ‘2~2p’ 用sed打印偶数行

2

4

6

8

10

####################################################################################################################################################

awk在文件中是一行一行执行的

awk控制语句if-else

语法 :if(condition){statement;…}[else statement]

if(condition1){statement1}else if(condition2){statement2}else{statement3}

使用场景:对AWK取得的整行活某个字段做条件判断

例: awk -F: ‘{if($3>=1000)print $1,$3}’ /etc/passwd

在/etc/passwd文件中如果第3列大于等于1000就打印第一列和第三列

-F: 以:为分隔符

$3 第三列

if 判断语句

if($3>=1000) 如果第3列大于等于1000

print $1,$3 打印第1列和第3列

例:awk -F: ‘{if($NF==”/bin/bash”)print $1,$7}’ /etc/passwd

在/etc/passwd文件中如果以:为分隔符,如果在最后一列是/bin/bash,就打印第一列和第七列

-F: 以:为分隔符 也可以用 -v FS=:代替 FS是AWK的内部变量

$NF== :NF 是一行字段的数量,$NF代表最后一个字段 NF是awk的内部变量

if是判断语句

if($NF==”/bin/bash”) 如果最后一个字段是/bin/bash

print $1,$7 打印第例和第7列

例:awk ‘{if(NF>5)print $0}’ /etc/fstab

在/etc/fstab文件中如果一行的字段数大于5就打印一整行

例:awk -F: ‘{if($3>=1000){printf “Common user:%s\n”,$1}else{printf “root or Sysuer:%s\n”,$1}}’ /etc/passwd

在/etc/passwd文件中如果第三列大于等于1000就执行Common user: %s\n”,$1,如果不是大于等于1000就执行root or Sysuer: %s\n”,$1

$1 是第一列

-F:是以:号为分隔符

if 判断语句

{if($3>=1000) 如果第三列大于等于1000

%s 显示字符串

\n 回车,printf默认不会换行

{printf “Common user:%s\n”,$1} 打印Common user:和第一列

else 如果第三列不是大于等于1000就执行

{printf “root or Sysuer:%s\n”,$1} 打印root or Sysuer:和第一列

或 :awk -F: ‘{if($3>=1000)printf “Common use:%s\n”,$1;else printf “root or sysuwer:%s\n”,$1}’ /etc/passwd

例 :df -h |awk -F% ‘/^\/dev\/sd/{print $1}’ |awk ‘$NF>=10{print $1,$5}’

在df -h命令中,先以%为分隔符,切割/dev/sd开头的行,切割第一列,在以空格为分隔符,打印第一列和第五列最后一个字段是大于等于10的行

-F% 以%为分隔符

/^\/dev\/sd/ 以/dev/sd开头的行 ,awk支持正则表达式,在正则表达式里面/号要加\转义

{print $1} 打印一%百分号为分隔符的第一列

awk ‘$NF>=10{print $1,$5}’

$NF>=10 最后一列小于等于10 NF是awk的内置变量,代表一行有多少字段,$NF代表最后一个字段

{print $1,$5} 打印第一列和第五列

例 :awk ‘BEGIN{test=100;if(test>90){print “very good”}else if(test>60){print “good”}else{print “no pass”}}’

定义一个值test=100 ,如果test大于90就打印very good ,如果text大于60就打印good,如果都不是就打印no pass

BEGIN 不用输出文件

test=100 定义一个test值

if判断语句

if(test>90) 如果大于90

{print “very good”} 打印 very good

else 如果不符合上一条判断

if(test>60) 如果test大于60

{print “good”} 打印 goot

else 如果不符合上一条判断

{print “no pass”} 打印no pass

####################################################################################################################################################

while 循环

语法:while(condition){statement;…}

条件“真”,进入循环;条件“假”,退出循环

使用场景:

对一行内的多个字段逐一类似处理时使用

对数组中的各元素逐一处理时使用

awk在文件中是以一行一行执行的

例 :awk ‘/^[[:space:]]*linux16/{i=1;while(i<=NF){print $i,length($i);i++}}’ /etc/grub2.cfg

在/etc/grub2.cfg 文件中以没有空格或多个空格且包含Linux16开头的行,i定义一个值为1 循环,如果i小于等于一行的字段数,就打印第一列和这一列的字符数,执行后i加1

[[:space:]] 代表空格

* 代表没有或一个或多个

^ 在正则表达式中代表开头

/^[[:space:]]*linux16/ 代表以没有空格或多个空格且包含Linux16开头的行

i定义一个值为1

while 代表循环

(i<=NF) i代表1 NF代表一行的字段的数量 i小于等于字段数

length 代表一个字段有多少字符

length($i) i的字段有多少字符

i++ 当第一次循环往i加一 ,i变成2 i=2 ….i=5 直到符合i小于字段数的判断在停止循环 awk在文件中是以一行一行执行的

{print $i,length($i);i++}} 打印i的字段,和i字段的字符数,在i加1 直到符合i小于字段数的判断在停止循环 awk在文件中是以一行一行执行的

例 :awk ‘/^[[:space:]]*linux16/{i=1;while(i<=NF) {if(length($i)>=10) {print $i,length($i)};i++}}’ /etc/grub2.cfg

在/etc/grub2.cfg文件中以没有空格或多个空格且包含Linux16开头的行,i定义一个值为1 循环判断i是否小于等于字段数 ,如果i的字段数大于等于10,就打印i的列,和i列的字符数,在循环

[[:space:]] 代表空格

* 代表没有或一个或多个

^ 在正则表达式中代表开头

/^[[:space:]]*linux16/ 代表以没有空格或多个空格且包含Linux16开头的行

i定义一个值为1

while 代表循环

(i<=NF) i代表1 NF代表一行的字段的数量 i小于等于字段数

length 代表一个字段有多少字符

length($i) i的字段有多少字符

if 判断语句

{if(length($i)>=10) 如果i字段的字符数大于等于10

i++ 当第一次循环往i加一 ,i变成2 i=2 ….i=5 直到符合i小于字段数的判断在停止循环 awk在文件中是以一行一行执行的

{print $i,length($i)};i++}} 打印i的字段,和i字段的字符数,在i加1 直到符合i小于字段数的判断在停止循环 awk在文件中是以一行一行执行的

do-while循环

语法:do {statement;…}while(condition)

意义:无论真假,至少执行一次循环体

例 :awk ‘BEGIN{ total=0;i=0;do{ total+=i;i++;}while(i<=100);print total}’

计算1到100的相加的和

BEGIN只执行一次,不用输出文件

total=0 total定义一个值为0

i=0 i定义一个值为0

do 先执行一次

total+=i 代表total=total+i

i++ 当一次循环完成i+1

while 循环

while(i<=100) 判断i小于等于100

print total 打印total

***********************************************************************************************************************************************88

bash for循环 判断1到100相加的和

#!/bin/bash

sum=0 #定义一个值

for ((i=0;i<=100;i++));do

let sum+=i

done

echo sum=$sum

**************************************************************************************************************************************************************

switch语句

语法:switch(expression) {case VALUE1 or /REGEXP/: statement1; case

VALUE2 or /REGEXP2/: statement2; …; default: statementn}

例:awk ‘BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==0)continue;sum+=i}print sum}’

计算1到100偶数的和

BEGIN,不用输入文件

sum=0 定义一个值为0

for循环

i=1 i定义一个值为0

i++ 当第一次循环往i加一 ,i变成2 i=2 ….i=5 直到符合i小于字段数的判断在停止循环 awk在文件中是以一行一行执行的

for(i=1;i<=100;i++) 判断i是否小于100,不小于加1

i%2==0 i取模2等于0 代表偶数

continue 取消本次循环,继续下一次循环

sum+=i 代表sum等于sum加i

print sum 打印sum的值

例 :awk ‘BEGIN{sum=0;for(i=1;i<=100;i++){if(i==66)break;sum+=i}print sum}’

BEGIN,不用输入文件

sum=0 定义一个值为0

判断i是否小于100,不小于加1

if(i==66) 判断如果i等于66

break 取消全部循环

um+=i 代表sum等于sum加i

print sum 打印sum的值

next:

提前结束对本行处理而直接进入下一行处理(awk自身循环)

例 :awk -F: ‘{if($3%2!=0) next;print $1,$3}’ /etc/passwd

在/etc/passwd文件中判断如果第3列是奇数就不执行这一行,打印的一列和第三列

-F: 以:冒号为分隔符

if 判断

$3%2 第三列取模2

!=0 不等于0

{if($3%2!=0) 如果第2例取模不等于0,就是奇数

next 结束这一行的处理

print $1,$3 打印第一列和第三列

例 :awk -F: ‘{if($3>10 && $3<100)print $1,$3}’ /etc/passwd

在/etc/passwd文件中查找大于10并且小于100的行,并打印第一列和第三列

***********************************************************************************************************************************************

awk的数组,它认为就是关联数组,自定义索引也叫下标

数组就是一个数组里面放多个值,数组分为普通数组和关联数组

例 :awk ‘BEGIN{title[“ceo”]=”mage”;title[“coo”]=”zhangsir”;print title[“coo”]}’

定义数组title 在title的数组中下标ceo的值是mage,coo下标的值是zhangsir ,打印title 数组的coo下标的值

BEGIN,不用输入文件

title 数组 名字自定义

[“ceo”] 下标,因为是关联数组所以下标自定义

[“coo”] 自定义下标

print title[“coo”]} 打印title 数组的coo下标的值

例:[root@centos7 ~]#cat f1.txt

aaa

bbb

ccc

aaa

bbb

ccc

ddd

ddd

eee

vvv

eee

[root@centos7 ~]#awk ‘!arr[$0]++’ f1.txt 去掉重复的行

aaa

bbb

ccc

ddd

eee

vvv

awk在文件中是一行一行执行的

在awk在1为真,0为假

$0是代表整行

arr[$0] 第一行是arr[aaa] 因为没有值代表空,就是假不打印

! 代表取反

!arr[$0]++ arr数组的值为空是0为假取反是1为真打印,当碰见重复的行的时候+1是2,2取反就是假不打印

***************************************************************************************************************************************************************

遍历

若要遍历数组中的每个元素,要使用for循环

for(var in array) {for-body}

注意:var会遍历array的每个索引

例 :awk ‘BEGIN{weekdays[“mod”]=”monday”;weekdays[“tue”]=”tuseday”;for(i in weekdays){print weekdays[i]}}’

显示所有下标的值

BEGIN 不用输出文件

weekdays 数组

[“mod”] 自定义下标

“monday” 下标的值

for 循环

i 是变量

for(i in weekdays) 循环i不断的查找下标的值

print weekdays[i]} 打印数组下标的值

例 :netstat -nat |awk ‘/^tcp/{test[$NF]++}END{for(i in test){print i,test[i]}}’

在netstat -nat命令中,查找tcp开头的行,test数组的下标是每行的最后一个字段,如果每行的最后一个字段有相同的就加1,所有的行处理完成用END遍历显示,用for循环i对应的下标,打印最后一个字段和出现的次数

/^tcp/ 代表以tcp开头,在正则表达式中^代表开头

test 代表数组可以自定义,一个数组里面可以有多个值,在数组中一个下标对应一个值

$NF 代表一行的最后一个字段,NF代表一行的所有字段的数量

++ 出现相同的就追加

{test[$NF]++} 添加一个test的数组,下标是$NF一行的最后一个字段,如果最后一个字段相同就加一

END 所有的行处理完成,用总的遍历显示

for循环

i 是一个变量代表了test数组的下标,就是一行的最后一个字段

test[i] 打印数量

{print i,test[i]}} 打印 最后一个字段,和这个字段出现的次数

例 cat access_log_\(1\) | awk ‘/^[0-9]/{ip[$1]++}END{for(i in ip){print i,ip[i]}}’

计算在 cat access_log_\(1\) 文件中相同ip出现的次数

awk 默认移空格为分隔符

/^[0-9]/ 以0-9的数字开头

ip 定义一个数组

$1 代表第一列

++ 代表如果相同就追加1

{ip[$1]++} ip数组的下标是文件中的第一列,在第一列中如果有相同的加1

END 代表所有的行处理完成,用总的变量显示

for 循环

i是变量 代表数组ip的下标

{print i,ip[i]}} 打印下标也就是第一列, 和所出现次数

####################################################################################################################################################

将某个ip放到防火墙,让他ping不通自己

iptables -A INPUT -s 原地址ip -j REGEXP

iptables -A INPUT -s 172.20.110.34 -j REJECT 拒绝ip访问

iptables -vnL 查看防火墙

如果ip的连接数大于1000就把这个ip放入防火墙

for i in `cat access_log_\(1\) | awk ‘/^[0-9]/{ip[$1]++}END{for(i in ip){if (ip[i]>=1000) print i}}’`;do

iptables -A INPUT -s $i -j REJECT

done

如果ip的连接数大于10000就把这个ip放入防火墙

awk ‘/^[0-9]/{ip[$1]++}END{for(i in ip){if(ip[i]>=10000) print i}}’ access_log_\(1\) 取出大于连接数10000的ip

while read ip;do #read的意思是逐行处理

iptables -A INPUT -s $ip -j REJECT

done

iptables -vnL 查看防火墙

查看ip连接数量最大的前10个

awk ‘/^[0-9]/{ip[$1]++}END{for(i in ip){ print i,ip[i]}}’ access_log_\(1\) |sort -k2 -nr |head

head 默认切割前10个

计算在文件中出现的单词数量

cat /etc/rc.sysinit |awk ‘{for(i=1;i<=NF;i++){work[$i]++}}END{for(j in work){print j,work[j]}}’

NF 代表一行的字段数

{for(i=1;i<=NF;i++) 给i赋值为1 ,如果1小于字段数就加1 ,i变成2,在判断2是否小于一行的字段数,一直判断到i等于一行的字段数,在判断继续下一行

{work[$i]++} work是函数 $i代表一行单词的数量,如果一行中有重复的单词就加1

END 所有的行处理完成,用总的遍历显示

[root@centos6 ~]#cat kaos.txt

name score sex

mage 100 m

zhangsir 99 m

bai 90 f

li 100 f

统计男神和女神的考试成绩的平均成绩

awk ‘{if($NF==”m”){sum_m+=$2;num_m++}else{sum_f+=$2;num_f++}}END{printf “male:%.2f\nfemale:%.2f\n”,sum_m/num_m,sum_f/num_f}’ kaos.txt

awk ‘{num[$NF]++;SUM[$NF]+=$2 }END{printf “male:%.2f\nfemale:%.2f\n”,sum[“m”]/num[“m”],sum[“f”]/num[“f”]}’ kaos.txt

***********************************************************************************************************************************************************************************8

awk函数

awk自带的函数

rand():返回0和1之间一个随机数 随机数不能自己生成得借助srand

例: awk ‘BEGIN{srand();print rand()}’

length([s]):返回指定字符串的长度

sub(r,s,[t]):对t字符串进行搜索r表示的模式匹配的内容,并将第一个匹配的内容替换为s

例 [root@centos6 ~]#echo “2008:08:08 08:08:08″ | awk ‘sub(/:/,”-“,$1)’

2008-08:08 08:08:08 $1替换的是第一列的第一个

例:echo “2008:08:08 08:08:08″ | awk ‘sub(/:/,”-“,$2)’

2008:08:08 08-08:08 $2替换的第二列的第一个

gsub(r,s,[t]):对t字符串进行搜索r表示的模式匹配的内容,并全部替换为s所表示的内容

例:[root@centos6 ~]#echo “2008:08:08 08:08:08″ | awk ‘gsub(/:/,”-“,$1)’

2008-08-08 08:08:08 $1替换的是第一列的全部

例:echo “2008:08:08 08:08:08″ | awk ‘gsub(/:/,”-“,$2)’

2008:08:08 08-08-08 $2 替换的是第二的全部

例:echo “2008:08:08 08:08:08″ | awk ‘gsub(/:/,”-“,$0)’

2008-08-08 08-08-08 $0替换的是全部

split(s,array,[r]):以r为分隔符,切割字符串s,并将切割后的结果保存至array所表示的数组中,

第一个索引值为1,第二个索引值为2,…

例:netstat -tan | awk ‘/^tcp\>/{split($5,ip,”:”);count[ip[1]]++}END{for (i in count) {print i,count[i]}}’

计算ip地址重复出现的次数

猜你喜欢

转载自blog.51cto.com/10957928/2159898