awk 命令

164 阅读3分钟

概述

awksed命令类似,只不过sed擅长取行,awk命令擅长取列。(根据了解awk是一种语言,不过我们只关注他处理文本的功能,用的好的话几乎可以取代excel)
原理:一般是遍历一个文件中的每一行,然后分别对文件的每一行进行处理
用法:

awk [可选的命令行选项] 'BEGIN{命令 } pattern{ 命令 } END{ 命令 }'  文件名
if(condition) {statments}

if(condition) {statments} else {statements}

while(conditon) {statments}

do {statements} while(condition)

for(expr1;expr2;expr3) {statements}

break

continue

delete array[index]

delete array

exit

{ statements }

注意:

多个语句之间需用分号分隔;

语句之间可实现嵌套,但是需用花括号进行约束;

单个语句时可省略花括号。

if-else

语法:

if(condition) statement [else {statement}]

打印某几列

$ echo 'I love you' | awk '{print $3 $2 $1}'
youloveI
$ echo '192.168.1.1' | awk -F "." '{print $2}'
168

条件过滤

我们知道awk的用法是这样的,那么pattern部分怎么用呢?

awk [可选的命令行选项] 'BEGIN{命令 } pattern{ 命令 } END{ 命令 }'  文件名

$ cat score.txt
tom 60 60 60
kitty 90 95 87
jack 72 84 99
$ awk '$2>=90{print $0}' score.txt
kitty 90 95 87

判断语句

判断语句是写在pattern{ 命令 }命令中的,他具备条件过滤一样的作用,同时他也可以让输出更丰富

'/^' a 以a开头

'/^[ab]' 以a或者b开头

'/AAA' 匹配AAA字符串

$ awk '{if($2>=90 )print $0}' score.txt
kitty 90 95 87
$ awk '{if($2>=90 )print $1,"优秀"; else print $1,"良好"}' score.txt
tom 良好
kitty 优秀
jack 良好

BEGIN 定义表头

awk [可选的命令行选项] 'BEGIN{命令 } pattern{ 命令 } END{ 命令 }'  文件名

使用方法如下:

$ awk 'BEGIN{print "姓名 语文 数学 英语"}{printf "%-8s%-5d%-5d%-5d\n",$1,$2,$3,$4}' score.txt
姓名 语文数学英语
tom 60 60 60
kitty 90 95 87
jack 72 84 99

这里要注意,我为了输出格式好看,做了左对齐的操作(%-8s左对齐,宽8位),printf用法和c++类似。
不仅可以用来定义表头,还可以做一些变量初始化的工作,例如

$ awk 'BEGIN{OFMT="%.2f";print 1.2567,12E-2}'
1.26 0.12

这里OFMT是个内置变量,初始化数字输出格式,保留小数点后两位。

END 添加结尾符

和BEGIN用法类似

$ echo ok | awk '{print $1}END{print "end"}'
ok
end

数据计算

这个地方我要放大招了!上面的知识点你都记住了吗?

$ awk 'BEGIN{print "姓名 语文 数学 英语 总成绩"; \
sum1=0;sum2=0;sum3=0;sumall=0} \
{printf "%5s%5d%5d%5d%5d\n",$1,$2,$3,$4,$2+$3+$4;\
sum1+=$2;sum2+=$3;sum3+=$4;sumall+=$2+$3+$4}\
END{printf "%5s%5d%5d%5d%5d\n","总成绩",sum1,sum2,sum3,sumall}'\
 score.txt
姓名 语文 数学 英语 总成绩
  tom 60 60 60 180
kitty 90 95 87 272
 jack 72 84 99 255
总成绩 222 239 246 707

内置变量

NF:表示当前行有多少个字段,因此$NF就代表最后一个字段
NR:表示当前处理的是第几行
FILENAME:当前文件名
OFMT:数字输出的格式,默认为%.6g。表示只打印小数点后6 位
FS:input Field Separator,输入的字段分隔符,默认为空格;
OFS:Output Field Separator,输出的字段分隔符,默认为空格;
RS:input Record Separator,输入时的换行符,默认为\n;
ORS:Output Record Separator,输出时的换行符,,默认为
ARGC:命令行参数的个数;
ARGV:一个数组,保存命令行所给定的各参数。

$ awk -F ':' '{print NR ") " $1}' demo.txt
1) root
2) daemon
3) bin
4) sys
5) sync

内置函数

awk定义了很多内置函数,用awk来写shell脚本倒是一个不错的选择,但是大多数我们是用不上的,以下是常用函数

$ echo 1 2 | awk '{print $1+sqrt($2)}'

2.41421

随机数,先设置种子再随机

rand() 0 <= n < 1,srand([expr]) |将 rand 函数的种子值设置为 Expr 参数的值,或如果省略 Expr 参数则使用某天的时间。

$ echo 1 | awk 'BEGIN{srand()}{print rand()}'

0.929885
  • 字符串

image.png

-系统常用

image.png

  • 不常用算数

image.png

awk 统计请求次数

  • a[n]统计去重工具,可以理解为javamapn] 统计去重工具,可以理解为java map,n 为key

  • a[$n] 统计重复的

image.png

  • !a[$n] 统计不重复的

image.png

  • 统计关键字出现的频次
// ! 优先级高于++
// $1 指定字段
awk '{!a[$1]++}END{for(i in a){print a[i]," ",i}}' text.txt |sort -g
  • 统计总数(例如统计请求次数)
awk '{!a[$1]++}END{for(i in a){print a[i]," ",i}}' text.txt |sort -g|awk 'BEGIN{sum=0}{sum+=$1}END{print sum}'

  • sort 排序命令,常用命令参数如下
-n 按照数值大小排序 
-r 逆序
-k i 按照文件第i列排序,列与列之间的分隔默认使用空格 
-t s 指定列与列的分隔符为s,特殊的比如tab键,使用 -t$'\t' (待补充)

实例

//按照第一列逆序排序
awk '{!a[$1]++}END{for(i in a){print a[i]," ",i}}' text.txt |sort -k1 -nr

awk 指定打印列


{for (i=1;i<=NF;i++)printf('%s ',$i);print ""}

参考: www.cnblogs.com/weifeng1463…