awk - juedaiyuer/researchNote GitHub Wiki
#文本分析工具---awk#
简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理
完整的awk脚本通常用来格式化文本文件中的信息
#使用方法
awk '{/pattern/ action}' {filename}
##调用awk##
#命令行方式
#F参数选择分隔符
awk [-F field-separator] 'commands' file
#shell脚本方式
#!/bin/awk
#将所有的awk命令写在一个单独文件,然后调用
awk -f awk.script file
##入门实例##
$ last -n 5
juedaiyu pts/24 :0 Fri Jul 22 10:35 - 11:42 (01:06)
juedaiyu pts/12 :0 Fri Jul 22 09:45 - 11:42 (01:56)
juedaiyu pts/9 :0 Fri Jul 22 09:39 still logged in
juedaiyu pts/1 :0 Fri Jul 22 09:32 - 09:32 (00:00)
juedaiyu :0 :0 Fri Jul 22 09:11 still logged in
#如果只是显示最近登录的5个帐号
#awk工作流程:
#1.读入由\n换行符分割的一条记录,然后将记录按指定的域分隔符划分域
#2.$0表示所有域,$1表示第一个域...
#默认分隔符是'空白键'或'tab键'
last -n 5 | awk '{print $1}'
#只是显示/etc/passwd的账户
#用到了指定分隔符
$ cat /etc/passwd | awk -F ':' '{print $1}'
#只是显示账户和账户对应的shell,两者之间用tab键分割
cat /etc/passwd | awk -F ':' '{print $1"\t"$7}'
#只显示账户和shell,以逗号分割;添加列名name,shell;在最后一行添加"blue,/bin/nosh"
cat /etc/passwd | awk -F ':' 'BEGIN {print "name,shell"} {print $1","$2} END{print "blue,/bin/nosh"}'
#搜索/etc/passwd有root关键字的所有行
awk -F : '/root/' /etc/passwd
#找root开头
awk -F: '/^root/' /etc/passwd
#搜索/etc/passwd有root关键字的所有行,并显示对应的shell
awk -F: '/root/{print $7}' /etc/passwd
# (*)将会尝试匹配它可能检测到的最长的匹配
###结合集合使用awk####
awk '/a|1/ {print}' /etc/hosts
#匹配以K或k开始,后面跟着一个T的字符串
###筛选文本例子###
#food_prices.list
No Item_Name Quantity Price
1 Mangoes 10 $2.45
2 Apples 20 $1.50
3 Bananas 5 $0.90
4 Pineapples 10 $3.46
5 Oranges 10 $0.78
6 Tomatoes 5 $0.55
7 Onions 5 $0.45
#查找大于$2,结尾用*标记
awk '/ *\$[2-9]\.[0-9][0-9] */ { print $1, $2, $3, $4, "*" ; } / *\$[0-1]\.[0-9][0-9] */ { print ; }' food_prices.list
#上面的终端显示很糟
#printf的格式化输出
$ awk '/ *\$[2-9]\.[0-9][0-9] */ { printf "%-10s %-10s %-10s %-10s\n", $1, $2, $3, $4 "*" ; } / *\$[0-1]\.[0-9][0-9] */ { printf "%-10s %-10s %-10s %-10s\n", $1, $2, $3, $4; }' food_prices.list
#使用$0字段
awk '/ *\$[2-9]\.[0-9][0-9] */ { print $0 "*" ; } / *\$[0-1]\.[0-9][0-9] */ { print ; }' food_prices.list
###使用比较操作符
#food_list.txt
No Item_Name Quantity Price
1 Mangoes 45 $3.45
2 Apples 25 $2.45
3 Pineapples 5 $4.45
4 Tomatoes 25 $3.45
5 Onions 15 $1.45
6 Bananas 30 $3.45
#打印出数量小于等于30的行,并且在后面增加(**)
awk '$3 <= 30 { printf "%s\t%s\n", $0,"**" ; } $3 > 30 { print $0 ;}' food_list.txt
##内置变量##
ARGC 命令行参数个数
ARGV 命令行参数排列
ENVIRON 支持队列中系统环境变量的使用
FILENAME awk浏览的文件名
FNR 浏览文件的记录数
FS 设置输入域分隔符,等价于命令行 -F选项
NF 浏览记录的域的个数
NR 已读的记录数
OFS 输出域分隔符
ORS 输出记录分隔符
RS 控制记录分隔符
###内置变量的使用###
#统计/etc/passwd:文件名,每行的行号,每行的列数,对应的完整行内容
#awk -F ':' '{print "filename:" FILENAME ",linenumber:" NR ",columns:" NF ",linecontent:"$0}' /etc/passwd
##awk编程##
#统计/etc/passwd的账户人数
awk '{count++;print $0;} END{print "user count is ", count}' /etc/passwd
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}'
#以M为单位显示
ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print "[end]size is ", size/1024/1024,"M"}'
###条件语句###
类似于C
#统计某个文件夹下的文件占用的字节数,过滤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的表格里。由于hash不是顺序存储,因此在显示数组内容时会发现,它们并不是按照你预料的顺序显示出来的。数组和变量一样,都是在使用时自动创建的,awk也同样会自动判断其存储的是数字还是字符串。一般而言,awk中的数组用来从记录中收集信息,可以用于计算总和、统计单词以及跟踪模板被匹配的次数等等。
#显示/etc/passwd的账户
awk -F ':' 'BEGIN {count=0;} {name[count] = $1;count++;}; END{for (i = 0; i < NR; i++) print i, name[i]}' /etc/passwd
##炫酷功能##
#如何删除文件中的重复行,只保留不重复的
awk '!seen[$0]++' <filename>
##source##
- The GNU Awk User’s Guide
- linux awk命令详解
- awk 系列:如何使用 awk 和正则表达式过滤文本或文件中的字符串 evernote私人库