`

awk总结

 
阅读更多

 

awk介绍

AWK是一种优良的文本处理工具。它不仅是 Linux 中也是任何环境中现有的功能最强大的数据处理引擎之一。这种编程及数据操作语言(其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母)的最大功能取决于一个人所拥有的知识。
AWK 提供了极其强大的功能:可以进行样式装入、流控制、数学运算符、进程控制语句甚至于内置的变量和函数。它具备了一个完整的语言所应具有的几乎所有精美特性。实际上 AWK 的确拥有自己的语言:AWK 程序设计语言, 三位创建者已将它正式定义为“样式扫描和处理语言”。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。

免费的awk版本
贝尔实验室的awk
gawk
mawk
awka

 

 

 

 

 

awk调用方式

1.命令行方式
awk 'commands' file.txt	 #file.txt是待处理的文件

2.shell脚本方式
#! /bin/awk
#.....

3.将所有awk命令插入一个单独的文件
awk -f awk-script-file file.txt	 #awk-script-file中包含了awk执行的脚本,file.txt是待处理的文件

 

 

 

 

 

表达式,变量

#字符串
echo "" | awk '{a="aa" "bb"; print a}'
#结果
aabb

echo "" | awk '{a="aabb"; print a}' 
#结果
aabb

echo "" | awk '{a="123"; n=a+1; print n}' 
#结果
124

echo "" | awk '{n=0.03125; print n}' 
echo "" | awk '{n=3.125e-2; print n}' 
echo "" | awk '{n=0.003125E1; print n}'
#结果
0.03125

 

数值运算符优先级

运算符 描述
= += -= *= /= %= ^= **= 赋值
?: C条件表达式
|| 逻辑或
&& 逻辑与
~ ~! 匹配正则表达式和不匹配正则表达式
< <= > >= != == 关系运算符
空格 连接
+ - 加,减
* / & 乘,除与求余
+ - ! 一元加,减和逻辑非
^ *** 求幂
++ -- 增加或减少,作为前缀或后缀
$ 字段引用
in 数组成员

指数操作

awk 'BEGIN{ print 2^10}' 
awk 'BEGIN{ print 2**10}' 

 

 

 

 

 

内建变量

变量 描述
$n 当前记录的第n个字段,字段间由FS分隔。
$0 完整的输入记录。
ARGC 命令行参数的数目。
ARGIND 命令行中当前文件的位置(从0开始算)。
ARGV 包含命令行参数的数组。
CONVFMT 数字转换格式(默认值为%.6g)
ENVIRON 环境变量关联数组。
ERRNO 最后一个系统错误的描述。
FIELDWIDTHS 字段宽度列表(用空格键分隔)。
FILENAME 当前文件名。
FNR 同NR,但相对于当前文件。
FS 字段分隔符(默认是任何空格)。
IGNORECASE 如果为真,则进行忽略大小写的匹配。
NF 当前记录中的字段数。
NR 当前记录数。
OFMT 数字的输出格式(默认值是%.6g)。
OFS 输出字段分隔符(默认值是一个空格)。
ORS 输出记录分隔符(默认值是一个换行符)。
RLENGTH 由match函数所匹配的字符串的长度。
RS 记录分隔符(默认是一个换行符)。
RSTART 由match函数所匹配的字符串的第一个位置。
SUBSEP 数组下标分隔符(默认值是\034)

内建变量操作

#FNR相当于文件行号 
for i in {a..j}; do echo $i; done | awk '{print FNR}' 

#每行的字段个数 
for i in {a..j}; do echo $i; done | awk '{print NF}' 

#已经读出的记录数,就是行号(不是输入文件的行号) 
for i in {a..j}; do echo $i; done | awk '{print NR}' 

#修改输出字段分隔符 
echo "aa bb cc dd" | awk 'BEGIN{OFS="@"} {print $1,$2,$3}' 


#修改输入记录的分隔符(默认是\n) 
echo "aa-bb-cc-dd-ee" | awk 'BEGIN{RS="-"} {print $1}' 

#修改输出记录的分隔符(默认是\n) 
cat hehe.txt | awk 'BEGIN{ORS="@"} {print $1} END{print "\n"}' 



#将每行打印到一个特定的文件中,这个文件名就是字段六(比如TIME_WAIT,LISTEN) 
netstat -anpt | awk 'NR!=1{print > $6}' 

 

 

 

 

 

数组变量

telephone["Alice"] = "555-0134"
telephone["Bob"] = "555-0135"
telephone["Carol"] = "555-0136"
telephone["Don"] = "555-0141"
这种数组称为关联数组,可以定义
x[1] = 3.14
x[10000] = "test"
之间不需要填满2-99999个元素,所以这些存储空间是稀疏的
del x[1]  	#删除数组x中的元素
del x	 #删除数组x 的所有元素

echo "" | awk '{a["test"]=100; a["hehe"]=123; a[100]=99; for(i in a){print i,a[i]} }'  
#结果,i是key,a[i]是value
100 99
test 100
hehe 123

 

 

 

 

 

环境变量

#内建变量 ENVIRON(注意大写小)可以获取所有系统环境变量,也就是env命令中的所有值
echo "" | awk '{print "hostname=" ENVIRON["HOSTNAME"]; print "shell=" ENVIRON["SHELL"]; print "user=" ENVIRON["USER"]; }'
#结果
hostname=test-vm
shell=/bin/bash
user=root

#可以获得自定义的系统变量
export aaa=hehe
echo "" | awk '{print ENVIRON["aaa"]}'

 

 

 

 

 

命令行参数

#使用ARGC获得传入的命令参数长度
#使用ARGV获得向量数组,获取参数值
awk  'BEGIN{print "ARGC=" ARGC;   for(j=0;j<ARGC;j++){print "ARGV[" j "]=[" ARGV[j] "]" } }' hehe.txt aa=bb ?? a1=1
#结果
ARGC=5
ARGV[0]=[awk]
ARGV[1]=[hehe.txt]
ARGV[2]=[aa=bb]
ARGV[3]=[??]
ARGV[4]=[a1=11]

 

 

 

 

 

字段和分隔符

#默认是空格分隔
echo "aa bb cc dd" | awk '{print $1 " - " $2}'

#指定一个特定的分隔符
#$1就是第一个字段。$2是第二个字段,以此类推
echo "aa@bb@cc@dd" | awk -F "@" '{print $1 " - " $2}'

#还可以写成
echo "aa@bb@cc@dd" | awk 'BEGIN{FS="@"} {print $1 " - " $2}'  

#分隔符可以有多个字符组成,这点比cut强
echo "aa=@#=bb=@#=cc=@#=dd" | awk -F "=@#=" '{print $1 " - " $2}'

 

 

 

 

 

模式与操作

awk程序的操作模式如下

命令 含义
pattern {action} 如模式匹配,则执行操作
pattern 如模式匹配,则打印记录
            {action} 针对每条记录,执行操作

 

#匹配一个模式,执行操作
echo "aa bb cc dd" | awk '/aa/ {print $3}'

#可以匹配多个模式,/pattern/ && /pattern/ 这种形式
for i in {a..j}; do echo $i; done | awk '/c/ || /d/ || /e/ || !/[f-z]/ {print $1}' 

#使用 $1 ~ /pattern/ 这种形式可以针对某个特定字段进行匹配,同样可以匹配
#多个字段或者多个模式
for i in {a..j}; do echo $i; done | awk '$1 ~ /c/ || $1 ~/d/ || $1 !~/[e-z]/ {print $0}'

#使用if匹配
for i in {a..j}; do echo $i; done | awk '{if($1=="c"){print "ok!"} }'



#BEGIN:让用户指定在第一条输入记录被处理之前所发生的动作,通常可在
#这里设置全局变量。
for i in {a..j}; do echo $i; done | awk 'BEGIN{print "BEGIN"}' 

#END:让用户在最后一条输入记录被读取之后发生的动作。
for i in {a..j}; do echo $i; done | awk 'END{print "END!"}' 

#范围匹配,匹配第一个c的行和第一个f行,并打印这些行 
for i in {a..j}; do echo $i; done | awk '/c/, /f/{ print "-->"$1}' 

 

 

 

 

 

选择和循环

 

#放到awk_test.sh中
#if和else if多重判断 
echo "" | awk '{ 
    srand(); 
    num = rand() * 10; 
    if(num < 3) { 
        print "num < 3" 
    } 
    else if(num > 3 && num < 5) { 
        print "num>3 && num<5" 
    } 
    else if(num < 9) { 
        print "num < 9" 
    } 
    else { 
        print "unknow..." 
    } 
}' 

#while循环 
echo "" | awk '{i=1; while(i<5){print i; i++}}' 

#do while 
echo "" | awk '{ i=1; do{print i; i++;}while(i<5) }'

#for循环 
echo "" | awk '{ for(i=0;i<5;i++){print i} }' 

#for each循环 
#求出netstat的状态,获取10行,然后记录到关联数组中,最后遍历关联数组并打印 
netstat | head | awk '{print $6}' | sed '/^$/d' | awk '{sum[$1]++} END{ for(s in sum){print s ","sum[$1]} }' 
 

 

 

 

 

 

用户控制的输入

getline的各种用法

命令 含义
getline 从当前输入文件中,读取下一条记录,存入$0,并更新NF,NR和FNR
getline var 从当前输入文件中,读取下一条记录,存入var,并更新NR和FNR
getline < file 从file中读取下一条记录,存入$0,并更新var
getline var < file 从file中读取下一条记录,存入var
cmd | getline 从外部命令cmd读取下一条记录,存入$0,并更新NF
cmd | getline var 从外部命令cmd读取下一条记录,存入var

 

用户输入和外部命令

 

#getline读取下一行 
awk '/^1/ && /1$/ {getline; print $0}' hehe.txt ' 

#读取命令行的结果 
echo "" | awk '{"date" | getline var ; print var}' 

#这里的命令行结果有多行,但是echo "" 只有一行,所以awk的{} 
#语句只执行一次 
#这样只能读取ls -l 中的第一行了,如果要读取ls -l的全部结果,需要保证 
#echo "" 这样的语句返回的行数和ls -l的行数一样才可以 
echo "" | awk '{"ls -l" | getline var; print var}' 

#想要全部读取可以使用这种方式 
echo "" | awk '{command="head -n 10 /etc/passwd"; while((command | getline s) > 0){print s;} }' 

#通过system()函数调用外部命令,此时可以返回全部结果 
echo "" | awk '{system("ls -l")}' 

#重定向输出 
awk '{print $0 > "/data0/test/test.log"}' hehe.txt 

#next,当碰到netx会忽略掉next之后的所有语句然后读取下一行继续执行 
seq 10 | awk '{ if($1==3){next;} print $0 }' 

 

 

 

 

数学函数

函数名 含义
atan2( y, x ) 返回 y/x 的反正切
cos( x ) 返回 x 的余弦;x 是弧度
sin( x ) 返回 x 的正弦;x 是弧度
exp( x ) 返回 x 幂函数
log( x ) 返回 x 的自然对数
sqrt( x ) 返回 x 平方根
int( x ) 返回 x 的截断至整数的值
rand( ) 返回任意数字 n,其中 0 <= n < 1
srand( [Expr] )

将 rand 函数的种子值设置为 Expr 参数的值,

或如果省略 Expr 参数则使用某天的时间。返回先前的种子值

 

演示

echo "" | awk '{print atan2(10,2)}' 
echo "" | awk '{print cos(10)}' 
echo "" | awk '{print exp(10)}' 
echo "" | awk '{print int("11@@111111111??11111ss")}'	#结果11 
echo "" | awk '{print log(10)}' 
echo "" | awk '{x=rand(); print x}' 
echo "" | awk '{print sin(90)}' 
echo "" | awk '{print sqrt(100)}' 

 

 

 

 

 

时间函数

函数名 含义
mktime( YYYY MM DD HH MM SS[ DST]) 生成时间格式
strftime([format [, timestamp]]) 格式化时间输出,将时间戳转为时间字符串 具体格式
systime()

得到时间戳,返回从1970年1月1日开始到当前

时间(不计闰年)的整秒数

 

strftime

格式 描述
%a 星期几的缩写(Sun)
%A 星期几的完整写法(Sunday)
%b 月名的缩写(Oct)
%B 月名的完整写法(October)
%c 本地日期和时间
%d 十进制日期
%D 日期 08/20/99
%e 日期,如果只有一位会补上一个空格
%H 用十进制表示24小时格式的小时
%I 用十进制表示12小时格式的小时
%j 从1月1日起一年中的第几天
%m 十进制表示的月份
%M 十进制表示的分钟
%p 12小时表示法(AM/PM)
%S 十进制表示的秒
%U 十进制表示的一年中的第几个星期(星期天作为一个星期的开始)
%w 十进制表示的星期几(星期天是0)
%W 十进制表示的一年中的第几个星期(星期一作为一个星期的开始)
%x 重新设置本地日期(08/20/99)
%X 重新设置本地时间(12:00:00)
%y 两位数字表示的年(99)
%Y 四位表示的年
%Z 时区(PDT)
%% 百分号(%)

 

演示

#当前时间戳 
echo "" | awk '{print systime()}'	

#格式化当前时间,strftime是c的函数,可以参考man strftime 
echo "" | awk '{x=systime(); print strftime("%Y-%m(%B)-%d %H:%M:%S %A",x);}' 

#mktime,c里面也有这个函数,可以参考man mktime 

 

 

 

 

 

字符串函数

函数 含义
gsub( Ere, Repl, [ In ] ) 除了正则表达式所有具体值被替代这点,它和 sub 函数完全一样地执行
sub( Ere, Repl, [ In ] )

用 Repl 参数指定的字符串替换 In 参数指定的字符串中的由

Ere 参数指定的扩展正则表达式的第一个

index( String1, String2 )

在由 String1 参数指定的字符串(其中有出现 String2 指定的参数)中,

返回位置,从 1 开始编号

length [(String)] 返回 String 参数指定的字符串的长度(字符形式)
substr( String, M, [ N ] )

返回具有 N 参数指定的字符数量子串。子串从 String 参数

指定的字符串取得,其字符以 M 参数指定

match( String, Ere )

在 String 参数指定的字符串(Ere 参数指定的扩展正则表达式出现在其中)

中返回位置(字符形式)

split( String, A, [Ere] )

将 String 参数指定的参数分割为数组元素 A[1], A[2], . . ., A[n],

并返回 n 变量的值。此分隔可 

tolower( String )

返回 String 参数指定的字符串,字符串中每个大写字符将更改为小写。

大写和小写的映射由当前语言环境的

toupper( String )

返回 String 参数指定的字符串,字符串中每个小写字符将更改为大写。

大写和小写的映射由当前语言环境的

sprintf(Format, Expr, Expr, . . . )

根据 Format 参数指定的 printf 子例程格式字符串来格式化

Expr 参数指定的表达式并返回

printf

格式化 含义
%d 十进制有符号整数
%u 十进制无符号整数
%f 浮点数
%s 字符串
%c 单个字符
%p 指针的值
%e 指数形式的浮点数
%x %X 无符号以十六进制表示的整数
%o 无符号以八进制表示的整数
%g 自动选择合适的表示法

 

演示

#替换第一个出现的aa 
echo "" | awk '{x="aa aa bb cc aa aa xx "; sub("aa","AA",x); print x}' 
#结果 
AA aa bb cc aa aa xx 

#替换所有的aa 
echo "" | awk '{x="aa aa bb cc aa aa xx "; gsub("aa","AA",x); print x}' 
#结果 
AA AA bb cc AA AA xx 


echo "" | awk '{print index("x~!#@# aa bb cc xxx aa ss","aa")}' 
#结果 
8 

echo "" | awk '{print index("aa bb cc xxx aa ss","aa")}' 
#结果 
1 

echo "" | awk '{print length("abcdefghij")}' 
echo "" | awk '{print tolower("sdfsdfAAsdf%%SsdfFJGJ")}' 
echo "" | awk '{print toupper("sdfsdfAAsdf%%SsdfFJGJ")}' 
echo "" | awk '{print match("hehe999^%^>>???hehe","[0-9]")? "ok~" : "not found"}' 

echo "" | awk '{a="1234567890aaaaaabbbb"; print substr(a,3,5);}' 
#结果 
34567 

echo "" | awk '{x="aa@bb@cc@dd"; split(x,y,"@"); for(i in y){print i"-"y[i]} }' 
#结果 
4-dd 
1-aa 
2-bb 
3-cc 

#格式化字符串 
echo "" | awk '{printf("%s--%d--%f\n","aaaa",111,3.14)}' 

 

 

 

 

 

自定义函数

其他函数 

位操作函数 

国际化函数

#欧几里得算法 
#执行方式 
echo "" | awk -f gcg.awk 
#! /bin/awk 
function gcd(x, y) { 
x = int(x); 
y = int(y); 

print x, y 
r = x % y; 
return (r==0) ? y : gcd(y,r); 
} 

{ 
g = gcd($1, $2); 
print "gcd(" $1 "," $2 ")=" g; 

} 

 

#打印5行随机数 
for k in {1..5}; do awk 'BEGIN{ srand(); for(k=1;k<=5;k++){printf("%.5f\t",rand());}print }' sleep 1; done 

 

#反向查找函数 
#执行方式 
echo "" | awk -f rindex.awk 
#! /bin/awk 
function rindex(string, find, k, ns, nf) { 
    ns = length(string); 
    nf = length(find); 
    for(k=ns+1-nf; k>=1; k--) { 
        if(substr(string, k, nf) == find) { 
            return k; 
        } 
    } 
    return 0; 
} 

{ 
x = rindex("afsdfsdffffffx", "f",1,2,3); 
print x 
} 

 

#把数组中的字符串合在一起 
执行方式 
echo "" | awk -f join.awk 
#! /bin/awk 
function join(array) { 
    n = length(array); 
    if(n >= 1) { 
        s = array[1]; 
        for(k=2;k<=n;k++) { 
            s = s "-" array[k]; 
        } 
    } 
    return s; 
} 

{ 
a[1] = "aaa"; 
a[2] = "bbb"; 
a[3] = "ccc"; 
a[4] = "ddd"; 
a[5] = "eee"; 
print join(a); 
} 

 

 

 

 

 

参考

awk百科

linux awk命令详解

Awk学习笔记

AWK简明教程

awk英文版手册

linux awk内置函数详细介绍

awk man介绍和man strftime介绍

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics