资讯专栏INFORMATION COLUMN

三剑客之AWK

csRyan / 1291人阅读

摘要:使用中,需要处理的文件,逐行使用分隔符分割成若干个字段,称之为域,分隔符默认是空格,可使用选项来指定分隔符脚本模式将所需执行的命令插入脚本文件,然后在首行设置命令解释器为通过键入脚本名的方式调用。

博文参考
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...直到最后一个,最后就可以对这些片多带带处理。

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 
hello 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

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





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 
 on an m
User:
awk -F: "{printf "User:%s
",$1}" /etc/issue
User:%s
表示对后面$1的内容以字符串形式显示,并且在其前面加上User:字符串,同时结尾添加换行符
awk -F" " "{printf "User:%s,UID:%d
",$1,$3}" /etc/issue
User:%s,UID:%d
表示对后面的$1的内容以字符串的形式显示,对$2后面内容十进制显示,同时结尾添加换行符。
awk -F" " "{printf"User:%-15s,UID:%15d
",$1,$3}" /etc/issue
左边一栏以左对齐方式显示15个字符长度,右边栏以默认对齐方式右对齐显示15个字符的长度
[root@mm ~]#awk -F, "{printf "first record:%s
",$1}" 1.sh

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

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/40626.html

相关文章

  • 【程序员必备】知识点 持续更新

    TCP/IP HTTP和HTTPS有何区别? httpbin 一个简单的HTTP请求和响应服务。 TCP的三次握手与四次挥手 通俗易懂版,详细版本 MySQL CHAR和VARCHAR存取的差别 《高性能MySQL》笔记 - MySQL 锁的基本类型 MySQL中的锁之一:锁的必要性及分类 MySQL中的锁之二:行锁、页锁、表锁 MySQL Like与Regexp的区别 数据结构 数...

    hellowoody 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<