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

⚠️ **GitHub.com Fallback** ⚠️