简介
awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。
使用方法
awk ‘{pattern + action}’ {filenames}
其中 pattern 表示 AWK 在数据中查找的内容,而 action 是在找到匹配内容时所执行的一系列命令。花括号({})不需要在程序中始终出现,但它们用于根据特定的模式对一系列指令进行分组。
举例子
- 显示最近登录的5个帐号
last -n 5 | awk '{print $1}'
- 显示/etc/passwd的账户
cat /etc/passwd |awk -F ':' '{print $1}'
- 显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以逗号分割,而且在所有行添加列名name,shell,在最后一行添加”blue,/bin/nosh”。
cat /etc/passwd |awk -F ':' 'BEGIN {print "name,shell"} {print $1","$7} END {print "blue,/bin/nosh"}'
awk工作流程是这样的:先执行BEGING,然后读取文件,读入有/n换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域, 0则表示所有域, 1表示第一个域,$n表示第n个域,随后开始执行模式所对应的动作action。接着开始读入第二条记录······直到所有的记录都读完,最后执行END操作。
- 搜索/etc/passwd有root关键字的所有行,并显示对应的shell
awk -F: '/root/{print $7}' /etc/passwd
这种是pattern的使用示例,匹配了pattern(这里是root)的行才会执行action(没有指定action,默认输出每行的内容)
awk内置变量
- 统计/etc/passwd:文件名,每行的行号,每行的列数,对应的完整行内容:
awk -F ':' '{printf("filename:%10s,linenumber:%s,columns:%s,linecontent:%s\n",FILENAME,NR,NF,$0)}' /etc/passwd
awk编程
变量和赋值
下面统计/etc/passwd的账户人数
awk '{count++;print $0;} END{print "user count is ", count}' /etc/passwd
count是自定义变量。之前的action{}里都是只有一个print,其实print只是一个语句,而action{}可以有多个语句,以;号隔开。
这里没有初始化count,虽然默认是0,但是妥当的做法还是初始化为0:
awk 'BEGIN {count=0;print "[start]user count is ", count} {count=count+1;print $0;} END{print "[end]user count is ", count}' /etc/passwd
统计某个文件夹下的文件占用的字节数
ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print "[end]size is ", size}'
注意,统计不包括文件夹的子目录。
条件语句
统计某个文件夹下的文件占用的字节数,过滤4096大小的文件(一般都是文件夹):
ls -l |awk 'BEGIN {size=0;print "[start]size is ", size} {if($5!=4096){size=size+$5;}} END{print "[end]size is ", size/1024/1024,"M"}'
数组
因为awk中数组的下标可以是数字和字母,数组的下标通常被称为关键字(key)。值和关键字都存储在内部的一张针对key/value应用hash的表格里。一般而言,awk中的数组用来从记录中收集信息,可以用于计算总和、统计单词以及跟踪模板被匹配的次数等等。
条件操作符
<、<=、==、!=、>=、~匹配正则表达式、!~不匹配正则表达式
- 如果第四个域包含ASIMA,就打印整条
awk '{if ($4~/ASIMA/) print $0}' temp
- 只打印第3域等于”48”的记录
awk '$3=="3" {print $0}' temp
第一个域小于第2个域
awk '{if ($1<$2) print $1 "is smaller"}' temp
设置大小写: awk ‘/[Gg]reen/’ temp
AND与关系: awk ‘{if ( 1=="a" &&2==”b” ) print $0}’ temp
awk ‘{if ( 1=="a"|| 1==”b”) print $0}’ temp
awk内置字符串函数
gsub(r,s) 在整个$0中用s替代r
awk 'gsub(/name/,"xingming") {print $0}' temp
index(s,t) 返回s中字符串t的第一位置
awk 'BEGIN {print index("Suny","ny")}' temp
多个文件合并操作。
与其他命令配合使用
如果work_dir下的某个模块文件数大于20个则删除
WORK_DIR=/usr/locol/testmod
find ${WORK_DIR}_bk -maxdepth 1 -type d | grep -v "${WORK_DIR}_bk$" | xargs ls -ldt | awk -v service_name=$SERVICENAME '{if(NR>20 && $9 ~/'$service_name'/){print $9}}' | xargs rm -rf
该命令为找到当前目录上一级目录名称为testmod_bk
的文件夹。找到名称 为testmod_bk,按时间排序,如果记录大于 20,名册匹配则删除
第6 或7或8列匹配相应的名称则将相应的进程强制kill
ps ax | awk '($6 ~ "^'$BIN_DIR'") || ($7 ~ "^'$BIN_DIR'") || ($8 ~ "^'$BIN_DIR'") {print "kill -9 "$1;}' | /bin/sh 1>/dev/null 2>&1
将某个文件中的内容以固定的jason格式输出
源文件格式为
1 test.com abc.test.com
awk ’
BEGIN {FS=”\t”;}
FILENAME=="'$TMP_DIR'/test.list" {
printf "{";
printf "\"ID\":"$1", ";
printf "\"ZONE\":\""$2"\", ";
printf "\"DOMAIN\":"$3", ";
printf "\"CLASS\":\"IN\", ";
printf "\"TTL\":"600", ";
print "}";
}
' $TMP_DIR/test.list >$DATA_DIR/test.kxfr
输出后的文件
{“ID”:”1”,”ZONE”:”test.com”,”DOMAIN”:”abc.test.com”“,CLASS”:”IN”,“TTL”:600}
总结
awk功能强大。在文本处理方面比较优秀。能解决很多实际问题。另外AWK能与其他linux命令很好的配合使用。需要不断的练习才会熟练的使用。