awk 命令精讲

awk命令精讲

awk不仅仅是Linux系统的命令,也是一种编程语言,用来处理数据和生成报告(Exel),处理的数据可以是一个或多个文件(标准输入和管道获取标准输入)。可在命令行上编辑操作,也可以写成awk程序运用。

 

查看awk版本

# awk  --version

 

awk的格式

格式:# awk  -F “”  ‘’  文件路径

参数

-F 指定awk按照什么符号进行文本切割,将原文件内容切割成一列一列,如果不指定-F参数,awk默认按照空格进行文本切割

-F “”,””为分隔符

‘’

{} 代表print输出 输出多个值用逗号“,”分隔;{}中双引号里的内容原封不动输出

$ 代表取列

$1 代表第一列,以此类推 $0表示所有内容 $NF表示输出最后一列(最后一组元素)

 

 

 

 

 

 

 

awk指令是由模式、动作,或者模式和动作的组合组成。

awk  [awk参数]  ‘模式 {动作}’ 文件名

 

模式:过滤条件

动作:执行

在指定文件中,awk先根据分隔符进行切割,再在模式中过滤所需的数据,再通过动作去执行(无动作时,默认输出全部内容)

# awk -F “: ” ‘NR==3{print $1}’ yunjisuan.txt

 

 

 

 

 

 

 

指定分隔符种类

 

 

指定多个分隔符

 

 

 

 

 

 

多个模式和动作

 

 

 

 

awk执行过程示意图

从BEGIN模块开始,一行一行读数据,看模式,是否符合条件,符合则执行动作;若不符合,则执行下一行。执行到结尾,会执行END模块后输出文本内容

1)awk读入第一行内容

2)判断是否符合模式中的条件NR>=2

a,如果匹配则执行对应的动作{print $0}
b,如果不匹配条件,继续读取下一行

3)继续读取下一行
4)重复过程1-3,直到读取到最后一行(EOF:end of file)

 

 

 

awk格式

# awk  -F “参数”  ‘BEGIN{} 模式 {动作} END{}’ 文件名

 

BEGIN{}:告知awk,数据要如何读取

END{}:告知awk,程序要如何结束

 

分隔符

通过-F参数指定分隔符,换行符默认\n

(echo -e 显示换行识别\n  # echo -e “11223\nweer\n34455”)

NR这个符号的真正含义不是行号,二十数据被awk读取一段以后,NF就会记录一次。

由于awk默认以\n作为每次读取数据的结束标志,NR就恰好等于行号。

 

 

awk的换行符(读入换行符,输出换行符)

通过BEGIN{},在awk读取数据之前设定它的读入换行符、输出换行符

通常,默认awk的读入换行符和输出换行符为\n

 

RS 是输入记录分隔符,决定awk如何读取或分隔每行(记录)

ORS表示输出记录分隔符,决定awk如何输出一行(记录)的,默认是回车换行(\n)

FS是输入区域分隔符,决定awk读入一行后如何再分为多个区域。

OFS表示输出区域分隔符,决定awk输出每个区域的时候使用什么分隔他们。

awk无比强大,你可以通过RS,FS决定awk如何读取数据。你也可以通过修改ORS,OFS的值指定awk如何输出数据。

 

 

更改换行符,用RS,ORS操作

RS=””读入换行符(输入输出数据记录分隔符) ORS=””输出换行符(输出记录分隔符) NR 记录行号

 

 

当更改输出换行符时,输出换行符会替换掉读入换行符

 

 

因为设定了读入换行符RS=”:”,因此,在awk的内存里的数据是按照如下排列的:

1 root

2 x

3 0

4 0

5 root

6 /root

7 /bin/bash\nbin

8 x

9 1

10 1

 

由于awk默认输出换行符是\n,因此在输出时,awk会在内存行的每行结尾附加输出换行符号\n,因此输出时效果如下:

1 root

2 x

3 0

4 0

5 root

6 /root

7 /bin/bash

Bin

8 x

9 1

10 1

 

设置输出换行符ORS

 

 

按单词出现频率降序排序(计算文件中每个单词的重复数量)

 

 

方法(1)将所有非小写字母和非大写字母替换成空,剩余都是英文单词,再计数并排序

# cat count.txt | xargs -n1 | sort | uniq -c | sort -rn

 

 

sort 默认按26个字母排序(默认指定排序为第一列)

sort -n 按照数字大小排序

sort -r 倒序排序

sort -k 数字 从第“数字”列,按大小排序

 

uniq 相同元素去重

uniq -c 去重并计数

 

替换tr

格式

# tr  “”  “”

tr “a-z” “A-Z” 转换大小写

tr “:” ”?” 把:替换成?

 

 

 

 

方法(2)将文件里面的所有空格替换为回车换行符“\n”
# cat count.txt | tr " " "\n" | sort | uniq -c | sort -rn

 

方法(3)grep所有连续的字母,grep -o参数让他们排成一列

# grep -o "[a-zA-Z]\+" count.txt | sort | uniq -c | sort

 

awk的模式分类

(1)正则表达式模式

(2)比较表达式模式

(3)范围模式

(4)特殊模式BEGIN和END

 

正则表达式模式

 

显示第9列是200的行的IP地址

# awk ‘$9~/^200$/ {print $1}’ access.log

在第9列模式下,~进行正则匹配操作,以200开头,以200结尾过滤,

打印$1,显示IP地址

# awk ‘$9~/^404$/ {print $1}’ access.log | sort | uniq -c

在上述基础上,排序并去重、计数

或# awk ‘$9==”404” {print $1}’ access.log | sort | uniq -c

 

awk不支持的正则符号“{}”,需要加--posix或--re-interval实现

x{m}

x{m,}

x{m,n}

 

~ b表示进行正则匹配

!~ 表示与~相反

 

表示以第五列匹配正则表达式,过滤含有shutdown的字符串,显示这一行

# awk -F “:” ‘$5~/shutdown/’ yunjisuan.txt

 

 

 

显示姓zhang的人的第二次捐款金额及他的名字

# awk -F “[ :]+” ‘$1~/^zhang/ {print $2,$(NF-1)}’ /server/files/reg.txt

 

 

显示xiaoyu的姓氏和ID号码

# awk -F “[ : ]+” ‘$2~/^xiaoyu/ {print $1,3$}’ /server/files/reg.txt

 

 

显示所有以41开头的ID号码的人的全名和ID号码

# awk -F “[ :]+” ‘$3~/~41/ {print $1,$2,$3}’ /server/files/reg.txt

 

 

显示所有以一个D或X开头的人名全名

# awk -F “[: ]+” ‘$2~/^d|^x/ {print $1,$2}’ /server/files/reg.txt

 

 

显示所有ID号码最后一位数字是1或5的人的全名

# awk -F “[ :]+” ‘$3~/1$|5$/ {print $1,$2}’ /server/files/reg.txt

 

 

显示xiaoyu的捐款,每个值都有以$开头,如$520$200$135

# awk -F “[ :]+” ‘$2~/xiaoyu/ {print “$”$4”$”$5”$”$6}’ /server/files/reg.txt

 

 

 

显示所有人的全名,以姓、名的格式显示,如meng,feixue

# awk -F “[ :]+” ‘{print $1”,”$2}’ /server/files/reg.txt

 

 

 

取网卡eth0的IP地址

默认分隔符,第一个字符前面不占位

指定分隔符,第一个字符前面占位

方法一:

# ifconfig eth0 | awk ‘BEGIN{RS=”[ :]”} NR==31’

 

方法二:

# ifconfig eth0 | awk -F “(addr:)|(Bcast:)” ‘NR==2{print $2}’

 

 

方法三:

# ifconfig eth0 | awk -F “[ :]+” ‘NR==2{print $4}’

# ifconfig eth0 | awk -F “[ :]” ‘NR==2{print $13}’

 

 

方法四:

# ifconfig eth0 | awk -F “[^0-9.]+” ‘NR==2{print $2}’

 

 

 

 

比较表达式模式

取出文件/etc/services的23-30行

# awk ‘NR>=23&&NR<=30’ /etc/services

# awk ‘NR>22&&NR<31’ /etc/services

 

判断某一列是否等于某个字符,找出/etc/passwd中第五列是root的行

# awk -F":" '$5=="root"' /server/files/awk_equal.txt

# awk -F":" '$5~/^root$/' /server/files/awk_equal.txt

 

找出工资在(40000,60000)之间的员工名字

# awk -F: ‘$3>=”40000” && $3<=”60000” {print $1}’ test2

 

 

 

范围模式

显示第二行到第五行的行好和整行的内容

# awk 'NR==2,NR==5{print NR,$0}' count.txt

 

显示以bin开头,到第五行的行号及整行内容

# awk '/^bin/,NR==5{print NR,$0}' awkfile.txt

 

从第三列以bin开始的行到以lp开头的行并显示其行号和整行内容

awk -F":" '$5~/^bin/,/^lp/{print NR,$0}' awkfile.txt                     

 

从第三列以bin开头字符串的行到第三列以lp开头字符串的行

# awk -F: '$5~/^bin/,$5~/^lp/{print NR,$0}' awkfile.txt

 

 

BEGIN模块

(1)定义内置变量(-F本质式修改的FS变量)

# ifconfig eth0|awk -F "(addr:)|( Bcast:)" 'NR==2{print $2}'

相当于# ifconfig eth0 | awk 'BEGIN{FS="(addr:)|( Bcast:)"} NR==2{print $2}'

 

# ifconfig eth0 | awk -F "[ :]+" 'NR==2{print $4}'

相当于# ifconfig eth0 | awk 'BEGIN{FS="[ :]+"}NR==2{print $4}'

 

# ifconfig eth0 | awk -F "[^0-9.]+" 'NR==2{print $2}'

相当于# ifconfig eth0 | awk 'BEGIN{FS="[^0-9.]+"}NR==2{print $2}'

 

(2)在读取文件之前,输出提示性信息(表头)

# awk -F ":" 'BEGIN{print "1111","2222"} {print $1,$3} ' yunjisuan.txt

 

# awk -F ":" 'BEGIN{print "1111","2222"} {print $1,$3} END{print "asdf","asdfg"}' yunjisuan.txt

 

(3)使用BEGIN 模块的特殊性质,进行一些测试(计算)

计算数值

# awk 'BEGIN{print 10/3}'

 

 

赋值变量

# awk 'BEGIN{a=1;b=2;print a,b,a+b}'

 

 

awk中字母会被认为是变量,给一个变量赋值字母(字符串),用双引号

# awk 'BEGIN{abcd=123456;a=abcd;print a}'

123456

 

# awk 'BEGIN{a="abcd";print a}'

abcd

 

表示a的b次方

# awk ‘BEGIN{a=2;b=3;print a**b}’

 

查看/etc/services空行个数

 

# grep -c “^$” /etc/services   计数

 

 

# awk ‘/^$/ {i=i+1} END{print i}’ /etc/services

 

其中,i=i+1 等同于i++

 

查看test文件一共有多少行

# awk ‘{i++}END{print i}’ test

 

 

 

求test文件每行的值之和

# awk ‘{i=i+$0}END{print i}’ test

 

 

 

# awk‘{i=i+$1;print i,$1}’test

 

 

# awk‘{i=i+$1}END{print i}’test

 

 

求test文件每行的值之积(BEGIN初始变量设定位置)

# awk ‘BEGIN{i=1}{i=i*$1}END{print i}’ test

 

 

awk数组

用一个变量表示多组数据,通常优先考虑数组,eg:变量名[数字]=不同的值

awk数组结构

arrayname[string]=value

arrayname为数组名

string为元素名

value为值

 

循环语句

for(变量1 in 变量2) 表示变量1在变量2 中取值,变量1被变量2循环赋值

 

 

统计域名访问次数

(1)取出域名

(2)将域名去重

(3)统计次数

 

 

方法一:

# awk -F “/+” ‘{print $2}’ yuming | sort uniq -c

 

 

方法二:

# awk -F "[ /]+" '{h[$2]++}END{for(i in h)print i,h[i]}' yuming

 

 

 

统计域名访问次数并累计流量

(1)取出域名

(2)将域名去重

(3)统计流量大小

 

#  awk -F "[ /]+" '{h[$2]=h[$2]+$4}END{for(i in h)print i,h[i]}' yuming

 

 

第一列字母去重,并求和

 

 

# awk ‘{h[$1]+$2}END{for(i in h)print i,h[i]}’ test

 

 

 

 

 

WEB服务器日志文件

access.www.log

(企业应用) 分析图片服务日志,把日志(每个图片访问次数*图片大小的总和)排行,取top10,也就是计算每个url的总访问大小

(在Web服务器日志文件中查看哪个IP地址(用户)浏览本机次数,使用流量最多)

思路:用awk过滤出出现的IP地址,去重IP地址,统计其使用流量,并排序

说明:本题生产环境应用:这个功能可以用于IDC网站流量带宽很高,然后通过分析服务器日志哪些元素占用流量过大,进而进行优化或裁剪该图片,压缩js等措施。

本题需要输出三个指标:

【每个url访问次数】【访问次数*单个文件大小】【文件名(可以带URL)】

 

 

# cat access.www.log

# awk -F " +" 'BEGIN{i=1}{h[$1]=h[$1]*$9}END{for(i in h)print i h[i]}' access.www.log

 

 

posted @ 2018-10-29 21:02  zhoulang6  阅读(451)  评论(0编辑  收藏  举报