博文参考

http://www.178linux.com/6553
http://baike.baidu.com/link?url=Y4lo-kWxygpw7NLaKTSehvpkAM7ogKA6GPVxaM23MMSzjmfsx4o3mey7-VVqu1pDhZJqa0sr7cJNhggIHC5JT_

AWK简介

 awk是一种模式扫描和处理工具,相对于grep的查找,sed的编辑,它在对数据进行分析生成报表时显得尤为强大。awk通过逐行遍历一个或多个文件的方式,查找模式匹配到的行,而后以指定的分隔符(缺省为空格)进行切片,然后针对切片数据进行处理和分析。事实上,gawk有自己的语言,其本身就相当于一个解释器,允许用户创建简短的程序读取输入文件,对输入数据执行排序、计算以及生成报表操作,甚至可以类似bash shell实现诸如循环、数组、条件判断、函数、变量等功能,进而完成更为复杂的数据分析处理任务。

awk的使用方式

1、命令行方式:awk [-F field-separator] ‘COMMAND’inputfiles

//其中COMMAND是awk的执行命令,用来处理数据,[-F field-separator]是可选选项,inputfiles是待处理文件。

//awk使用中,需要处理的文件,逐行使用分隔符分割成若干个字段,称之为域,分隔符默认是空格,可使用-F选项来指定分隔符

2、shell脚本模式
将所需执行的awk命令插入awk脚本文件,然后在首行设置命令解释器为#!/bin/awk,通过键入脚本名的方式调用。

3、所有awk命令写入到一个单独的文件,当处理同一类文件需求时,使用awk -f awk-script inputfiles调用之,其中awk-script指awk脚本。

awk基本用法

awk[OPTIONS]'program'FILE1 FILE2...

program:PATTERN{ACTION STATEMENT}
program:编程语言
PATTERN:模式
ACTION STATEMENT:动作语句,可以有多个语句组成,各语句之间使用分号隔开;如:print,printf
OPTIONS:
    -F[]:指明输入字段分隔符
    -v VAR_NAME=VALUE:变量赋值
    -f /PATH/FROM/AWK_SCRIPT 指定脚本文件
awk处理文本按一行读取,根据输入分隔符切片(默认为空格字符),切n个片,然后将每个片赋予awk内部一个变量进行保存,其这个过程变量名为$1,$2,$3...直到最后一个,最后就可以对这些片单独处理。

clipboard.png

print输出命令

输出默认分割符:空白字符
item之间逗号分割
print " " 输出空白字符print $0 输出整行
awk [options] 'BEGIN{action}pattern{action}END{action}' file
awk 语法组成: BEGIN语句块,能够使用模式匹配的通用语句块,END语句块
awk执行时,由分隔符分割的字段(域)标记$1,$2,$n为域标识,$0为所有域
文件的每一行称为记录
省略action默认执行print $0操作

pattern 模式
action  动作;行为
row column  行,记录
record field 列,域,字段

案例

[root@mm ~]#echo -e "hello,world \nhello world" >1.sh
基本输出
[root@mm ~]#awk '{print $1}' 1.sh
引号的作用
[root@mm ~]#awk '{print "hi",$1}' 1.sh
[root@mm ~]#awk '{print "hi:$1"}' 1.sh
[root@mm ~]#awk '{print "hi:$1",666}' 1.sh
空白输出
[root@mm ~]#awk '{print}' 1.sh
[root@mm ~]#awk '{print ""}' 1.sh

awk默认从键盘输入,不管输入什么,输出都是hello
clipboard.png

变量

内置变量:
FS:输出字段分割符,默认空白
RS:输入时的行分割符,默认换行符
OFS:输出时的字段分割符,默认空白字符
ORS:输出时的行分割符,默认换行符
NF
    print NF:当前行的字段数
    print $NF:显示当前行的第NF字段的值
NR:行数;命令后跟的所有文件统一合并计算
FNR:行数;个文件单独计数
FILENAME:当前正被awk读取的文件名
ARGC:awk命令行中的参数个数
ARGV:数组,保存命令行参数本身
自定义变量:

clipboard.png
clipboard.png
clipboard.png
clipboard.png
clipboard.png

awk -F: 'END{print NF}' /etc/passwd #表示以:分割的有7段(显示总字段)
awk -F: '{print $(NF-1)}' /etc/passwd #取出最后一个字段的
awk -F: '{print NR,$1}' /etc/passwd #显示行号
awk '{print NR,$0}' /etc/issue /etc/fstab #两个文件合并显示行号
awk '{print FNR,$0}' /etc/issue /etc/fstab #两个文件分开显示行号
awk '{print FNR,$0,FILENAME}' /etc/issue /etc/fstab 显示文件名(FILENAME)

awk 'BEGIN{print ARGC}' /etc/issue /etc/fstab /etc/passwd #显示给的参数个数(BEGIN只显示一个参数)
awk 'BEGIN{print ARGC,ARGV[2]}' /etc/issue /etc/fstab /etc/passwd #根据参数的个数(索引)取出文件名([0]下标是awk)
awk 'BEGIN{print ARGC,ARGV[ARGC-2]}' /etc/issue /etc/fstab /etc/passwd #倒着显示给的参数
awk '{sex="male";print sex}' /etc/passwd #打印变量自定义sex
awk 'END{sex="male";print sex}' /etc/passwd #打印最后一个sex
awk '{sex="male";age=20;print sex,age}' /etc/passwd  #必须先定义再使用,不然第一个定义不到

案例

[root@mm ~]#awk -F, '{print $1}' 1.sh
[root@mm ~]#awk -v FS=',' '{print $1}' 1.sh
[root@mm ~]#awk -v FS=',' '{print $1,$2}' 1.sh
[root@mm ~]#awk -v FS=',' -v OFS='&' '{print $1,$2}' 1.sh
[root@mm ~]#awk -v RS=' ' '{print $1}' 1.sh
[root@mm ~]#awk -v RS=' ' -v ORS='-' '{print}' 1.sh
[root@mm ~]#awk '{print NF}' 1.sh
[root@mm ~]#awk '{print $NF}' 1.sh
[root@mm ~]#awk '{print NR}' 1.sh 2.sh
[root@mm ~]#awk '{print FNR}' 1.sh 2.sh
[root@mm ~]#awk '{print FILENAME}' 1.sh
[root@mm ~]#awk '{print ARGC}' 1.sh
[root@mm ~]#awk '{print ARGV[0]}' 1.sh 
[root@mm ~]#awk '{print ARGV[1]}' 1.sh
[root@mm ~]#awk -v hi="hi bro" '{print hi}' 1.sh
[root@mm ~]#awk '{hi="hi bro";print hi}' 1.sh

printf输出命令

%c:显示字符ASCLL码
%d,%i:十进制整数
%e,%E:科学计数法显示数值
%f:浮点数
%g,%G:科学计数法或浮点数 格式显示数值
%s:字符串
%u:无符号整数
%%:%符合本身

案例

[root@mm grub.d]#cat /etc/issue
User:Centos,UID:6
User:Kernel,UID:0    
User:, UID:0
User:CentOS release 6.6(Final)
User:Kernel \r on an \m
User:
awk -F: '{printf "User:%s\n",$1}' /etc/issue
User:%s\n表示对后面$1的内容以字符串形式显示,并且在其前面加上User:字符串,同时结尾添加换行符
awk -F' ' '{printf "User:%s,UID:%d\n",$1,$3}' /etc/issue
User:%s,UID:%d\n表示对后面的$1的内容以字符串的形式显示,对$2后面内容十进制显示,同时结尾添加换行符。
awk -F' ' '{printf"User:%-15s,UID:%15d\n",$1,$3}' /etc/issue
左边一栏以左对齐方式显示15个字符长度,右边栏以默认对齐方式右对齐显示15个字符的长度
[root@mm ~]#awk -F, '{printf "first record:%s\n",$1}' 1.sh

clipboard.png

三目表达式{条件满足 条件不满足?满足 执行命令:不满足 执行命令;打印%15是占位符($1) %-s是占位符(usertype) n (换行符) :(冒号分割符)}

awk -F: '{printf "%s",$1}' /etc/passwd #%s占位符,%s后加/n换行
awk  -F: '{printf "%s %4.2f\n",$1,$3}' /etc/passwd #%s是$1占位符;%4.2f指2位小数,$3的占位符
awk -F: '{printf "username:%-30s uid:%10d\n",$1,$3}' /etc/passwd #username(显示):(分割符)%-30s(%s是$1的占位符并且左对齐-30个字符) uid(显示):%10d(%d是$3的占位符10右对齐)\n(换行)",$1,$3

操作符

a.算数操作符
    -x:负值
    +x:转化为数值
b.字符操作符
c.赋值操作符
    =,+=,-=,*=,/=,%=,^=,++,--
d.比较操作符
    >,>=,<,<=,==,!=
awk -F: '!($3>=50){print $3}' /etc/passwd
e.模式匹配配操作符
    ~:是否能由右侧指定的模式所匹配
    ~!:是否不能由右侧指定模式所匹配
f.逻辑操作符
    &&:与运算
awk -F: '$3>=0 && $3<=1000 {print $1}' /etc/passwd
    ||:或运算
g.条件表达式
awk -F: '{$3>=500?usertype="Common User":usertype="Sysadmin or Sysuser";printf "%15s:%-s\n",$1,usertype}' /etc/passwd
h.函数调用

案例

[root@mm ~]#awk -F: '$3>=0 && $3<=1000 {print $1}' /etc/passwd
[root@mm grub.d]#awk -F: '!($3>=50){print $3}' /etc/passwd

[root@mm grub.d]#awk -F: 'BEGIN{print "username    uid \n------------"}{print $1,$3}END{print"========="}' /etc/passwd

PATTERN模式

1)empty:空模式,匹配所有行
2)/Regular Expression/:仅将ACTION应用于能够被Regular Expression所匹配到的行
awk -F: '/^[ab]/{print $1,$3}' /etc/passwd
3)relational expression:关系表达式,结果非0或非空字符串为真,否则为假;
awk -F: '$3>=500{print $1,$3}' /etc/passwd
awk -F: '$1~/root/{print $1,$3}' /etc/passwd
4)line ranges:行范围
5)BEGIN/END
    BEGIN:格式化前用于输出表头或做一个预处理操作
    END:格式化后用于输出表尾或做出清理操作

案例

常用ACTION

1)EXPRESSIONS:变量赋值
2)Control Statements:控制语句
3)Compound Statements:复合语句
4)input statements
5)output statements 

控制语句

第一中用法:
1)if-else
awk -F: '{if($3>=500)print $1,$3}' /etc/passwd
[root@mm ~]#awk '{if(NF>=6)print NF,$0}' /etc/passwd
[root@mm ~]#awk '{if(NF>=6)print NF,$0}' /etc/passwd
[root@mm ~]#awk -F: '{if($3>=500){print $1,"is a common user"} else {print $1,"is a sysadmin or sysuser"}}' /etc/passwd
2)while 循环
awk '{i=1;while(i<=NF){if(length($i)>=6){print $i};i++}}' /etc/passwd
3)do-while 循环
4)for 循环
awk '{for(i=1;i<=NF;i++){if(length($i)>=6)print $i}}' /etc/issue
第二中用法:
5)swtich                                                                                    
6)break and continue
7)next:提前结束本行处理;提前进入下行处理操作
awk -F: '{if($3%2==0)next;print $1,$3}' /etc/passwd

数组

关联数组
    index-expression:可以使用任意字符
数组遍历

函数

1)内建函数
数值处理:rand():返回0至1之间的一个随机数
字符串处理:
length([s]):返回指定的字符串的长度
sub(r,s[,t]):
gsub(r,s[,t]):
split(s,a[,r]):
2)用户自定义函数 

经验

统计指定的web访问日志中各ip的资源访问次数
awk '{ip[$1]++}END{for(i in ip)print i,ip[i]}' /var/log/httpd/access_log 
统计当前系统上所有tcp连接的各种状态的个数
ss -tan|awk '!/^State/{state[$1]++}END{for(i in state)print i,state[i]}'

达龙
250 声望19 粉丝

天才是重复次数最多的人!


下一篇 »
三剑客之SED