Linux-awk总结

 

awk介绍

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

 

 

 

 

 

awk调用方式

  1. 1.命令行方式  
  2. awk 'commands' file.txt  #file.txt是待处理的文件  
  3.   
  4. 2.shell脚本方式  
  5. #! /bin/awk  
  6. #.....  
  7.   
  8. 3.将所有awk命令插入一个单独的文件  
  9. awk -f awk-script-file file.txt  #awk-script-file中包含了awk执行的脚本,file.txt是待处理的文件  

 

 

 

 

 

表达式,变量

  1. #字符串  
  2. echo "" | awk '{a="aa" "bb"; print a}'  
  3. #结果  
  4. aabb  
  5.   
  6. echo "" | awk '{a="aabb"; print a}'   
  7. #结果  
  8. aabb  
  9.   
  10. echo "" | awk '{a="123"; n=a+1; print n}'   
  11. #结果  
  12. 124  
  13.   
  14. echo "" | awk '{n=0.03125; print n}'   
  15. echo "" | awk '{n=3.125e-2; print n}'   
  16. echo "" | awk '{n=0.003125E1; print n}'  
  17. #结果  
  18. 0.03125  

 

数值运算符优先级

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

指数操作

  1. awk 'BEGIN{ print 2^10}'   
  2. 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)

内建变量操作

  1. #FNR相当于文件行号   
  2. for i in {a..j}; do echo $i; done | awk '{print FNR}'   
  3.   
  4. #每行的字段个数   
  5. for i in {a..j}; do echo $i; done | awk '{print NF}'   
  6.   
  7. #已经读出的记录数,就是行号(不是输入文件的行号)   
  8. for i in {a..j}; do echo $i; done | awk '{print NR}'   
  9.   
  10. #修改输出字段分隔符   
  11. echo "aa bb cc dd" | awk 'BEGIN{OFS="@"} {print $1,$2,$3}'   
  12.   
  13.   
  14. #修改输入记录的分隔符(默认是\n)   
  15. echo "aa-bb-cc-dd-ee" | awk 'BEGIN{RS="-"} {print $1}'   
  16.   
  17. #修改输出记录的分隔符(默认是\n)   
  18. cat hehe.txt | awk 'BEGIN{ORS="@"} {print $1} END{print "\n"}'   
  19.   
  20.   
  21.   
  22. #将每行打印到一个特定的文件中,这个文件名就是字段六(比如TIME_WAIT,LISTEN)   
  23. netstat -anpt | awk 'NR!=1{print > $6}'   

 

 

 

 

 

数组变量

  1. telephone["Alice"] = "555-0134"  
  2. telephone["Bob"] = "555-0135"  
  3. telephone["Carol"] = "555-0136"  
  4. telephone["Don"] = "555-0141"  
  5. 这种数组称为关联数组,可以定义  
  6. x[1] = 3.14  
  7. x[10000] = "test"  
  8. 之间不需要填满2-99999个元素,所以这些存储空间是稀疏的  
  9. del x[1]    #删除数组x中的元素  
  10. del x    #删除数组x 的所有元素  
  11.   
  12. echo "" | awk '{a["test"]=100; a["hehe"]=123; a[100]=99; for(i in a){print i,a[i]} }'    
  13. #结果,i是key,a[i]是value  
  14. 100 99  
  15. test 100  
  16. hehe 123  

 

 

 

 

 

环境变量

  1. #内建变量 ENVIRON(注意大写小)可以获取所有系统环境变量,也就是env命令中的所有值  
  2. echo "" | awk '{print "hostname=" ENVIRON["HOSTNAME"]; print "shell=" ENVIRON["SHELL"]; print "user=" ENVIRON["USER"]; }'  
  3. #结果  
  4. hostname=test-vm  
  5. shell=/bin/bash  
  6. user=root  
  7.   
  8. #可以获得自定义的系统变量  
  9. export aaa=hehe  
  10. echo "" | awk '{print ENVIRON["aaa"]}'  

 

 

 

 

 

命令行参数

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

 

 

 

 

 

字段和分隔符

  1. #默认是空格分隔  
  2. echo "aa bb cc dd" | awk '{print $1 " - " $2}'  
  3.   
  4. #指定一个特定的分隔符  
  5. #$1就是第一个字段。$2是第二个字段,以此类推  
  6. echo "aa@bb@cc@dd" | awk -F "@" '{print $1 " - " $2}'  
  7.   
  8. #还可以写成  
  9. echo "aa@bb@cc@dd" | awk 'BEGIN{FS="@"} {print $1 " - " $2}'    
  10.   
  11. #分隔符可以有多个字符组成,这点比cut强  
  12. echo "aa=@#=bb=@#=cc=@#=dd" | awk -F "=@#=" '{print $1 " - " $2}'  

 

 

 

 

 

模式与操作

awk程序的操作模式如下

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

 

  1. #匹配一个模式,执行操作  
  2. echo "aa bb cc dd" | awk '/aa/ {print $3}'  
  3.   
  4. #可以匹配多个模式,/pattern/ && /pattern/ 这种形式  
  5. for i in {a..j}; do echo $i; done | awk '/c/ || /d/ || /e/ || !/[f-z]/ {print $1}'   
  6.   
  7. #使用 $1 ~ /pattern/ 这种形式可以针对某个特定字段进行匹配,同样可以匹配  
  8. #多个字段或者多个模式  
  9. for i in {a..j}; do echo $i; done | awk '$1 ~ /c/ || $1 ~/d/ || $1 !~/[e-z]/ {print $0}'  
  10.   
  11. #使用if匹配  
  12. for i in {a..j}; do echo $i; done | awk '{if($1=="c"){print "ok!"} }'  
  13.   
  14.   
  15.   
  16. #BEGIN:让用户指定在第一条输入记录被处理之前所发生的动作,通常可在  
  17. #这里设置全局变量。  
  18. for i in {a..j}; do echo $i; done | awk 'BEGIN{print "BEGIN"}'   
  19.   
  20. #END:让用户在最后一条输入记录被读取之后发生的动作。  
  21. for i in {a..j}; do echo $i; done | awk 'END{print "END!"}'   
  22.   
  23. #范围匹配,匹配第一个c的行和第一个f行,并打印这些行   
  24. for i in {a..j}; do echo $i; done | awk '/c/, /f/{ print "-->"$1}'   

 

 

 

 

 

选择和循环

  1. #放到awk_test.sh中  
  2. #if和else if多重判断   
  3. echo "" | awk '{   
  4.     srand();   
  5.     num = rand() * 10;   
  6.     if(num < 3) {   
  7.         print "num < 3"   
  8.     }   
  9.     else if(num > 3 && num < 5) {   
  10.         print "num>3 && num<5"   
  11.     }   
  12.     else if(num < 9) {   
  13.         print "num < 9"   
  14.     }   
  15.     else {   
  16.         print "unknow..."   
  17.     }   
  18. }'   
  19.   
  20. #while循环   
  21. echo "" | awk '{i=1; while(i<5){print i; i++}}'   
  22.   
  23. #do while   
  24. echo "" | awk '{ i=1; do{print i; i++;}while(i<5) }'  
  25.   
  26. #for循环   
  27. echo "" | awk '{ for(i=0;i<5;i++){print i} }'   
  28.   
  29. #for each循环   
  30. #求出netstat的状态,获取10行,然后记录到关联数组中,最后遍历关联数组并打印   
  31. 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

 

用户输入和外部命令

  1. #getline读取下一行   
  2. awk '/^1/ && /1$/ {getline; print $0}' hehe.txt '   
  3.   
  4. #读取命令行的结果   
  5. echo "" | awk '{"date" | getline var ; print var}'   
  6.   
  7. #这里的命令行结果有多行,但是echo "" 只有一行,所以awk的{}   
  8. #语句只执行一次   
  9. #这样只能读取ls -l 中的第一行了,如果要读取ls -l的全部结果,需要保证   
  10. #echo "" 这样的语句返回的行数和ls -l的行数一样才可以   
  11. echo "" | awk '{"ls -l" | getline var; print var}'   
  12.   
  13. #想要全部读取可以使用这种方式   
  14. echo "" | awk '{command="head -n 10 /etc/passwd"; while((command | getline s) > 0){print s;} }'   
  15.   
  16. #通过system()函数调用外部命令,此时可以返回全部结果   
  17. echo "" | awk '{system("ls -l")}'   
  18.   
  19. #重定向输出   
  20. awk '{print $0 > "/data0/test/test.log"}' hehe.txt   
  21.   
  22. #next,当碰到netx会忽略掉next之后的所有语句然后读取下一行继续执行   
  23. 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 参数则使用某天的时间。返回先前的种子值

 

演示

  1. echo "" | awk '{print atan2(10,2)}'   
  2. echo "" | awk '{print cos(10)}'   
  3. echo "" | awk '{print exp(10)}'   
  4. echo "" | awk '{print int("11@@111111111??11111ss")}'   #结果11   
  5. echo "" | awk '{print log(10)}'   
  6. echo "" | awk '{x=rand(); print x}'   
  7. echo "" | awk '{print sin(90)}'   
  8. 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)
%% 百分号(%)

 

演示

C代码   收藏代码
  1. #当前时间戳   
  2. echo "" | awk '{print systime()}'     
  3.   
  4. #格式化当前时间,strftime是c的函数,可以参考man strftime   
  5. echo "" | awk '{x=systime(); print strftime("%Y-%m(%B)-%d %H:%M:%S %A",x);}'   
  6.   
  7. #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 自动选择合适的表示法

 

演示

  1. #替换第一个出现的aa   
  2. echo "" | awk '{x="aa aa bb cc aa aa xx "; sub("aa","AA",x); print x}'   
  3. #结果   
  4. AA aa bb cc aa aa xx   
  5.   
  6. #替换所有的aa   
  7. echo "" | awk '{x="aa aa bb cc aa aa xx "; gsub("aa","AA",x); print x}'   
  8. #结果   
  9. AA AA bb cc AA AA xx   
  10.   
  11.   
  12. echo "" | awk '{print index("x~!#@# aa bb cc xxx aa ss","aa")}'   
  13. #结果   
  14. 8   
  15.   
  16. echo "" | awk '{print index("aa bb cc xxx aa ss","aa")}'   
  17. #结果   
  18. 1   
  19.   
  20. echo "" | awk '{print length("abcdefghij")}'   
  21. echo "" | awk '{print tolower("sdfsdfAAsdf%%SsdfFJGJ")}'   
  22. echo "" | awk '{print toupper("sdfsdfAAsdf%%SsdfFJGJ")}'   
  23. echo "" | awk '{print match("hehe999^%^>>???hehe","[0-9]")? "ok~" : "not found"}'   
  24.   
  25. echo "" | awk '{a="1234567890aaaaaabbbb"; print substr(a,3,5);}'   
  26. #结果   
  27. 34567   
  28.   
  29. echo "" | awk '{x="aa@bb@cc@dd"; split(x,y,"@"); for(i in y){print i"-"y[i]} }'   
  30. #结果   
  31. 4-dd   
  32. 1-aa   
  33. 2-bb   
  34. 3-cc   
  35.   
  36. #格式化字符串   
  37. echo "" | awk '{printf("%s--%d--%f\n","aaaa",111,3.14)}'   

 

 

 

 

 

自定义函数

其他函数 

位操作函数 

国际化函数

  1. #欧几里得算法   
  2. #执行方式   
  3. echo "" | awk -f gcg.awk   
  4. #! /bin/awk   
  5. function gcd(x, y) {   
  6. x = int(x);   
  7. y = int(y);   
  8.   
  9. print x, y   
  10. r = x % y;   
  11. return (r==0) ? y : gcd(y,r);   
  12. }   
  13.   
  14. {   
  15. g = gcd($1, $2);   
  16. print "gcd(" $1 "," $2 ")=" g;   
  17.   
  18. }   

 

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

 

C代码   收藏代码
  1. #反向查找函数   
  2. #执行方式   
  3. echo "" | awk -f rindex.awk   
  4. #! /bin/awk   
  5. function rindex(string, find, k, ns, nf) {   
  6.     ns = length(string);   
  7.     nf = length(find);   
  8.     for(k=ns+1-nf; k>=1; k--) {   
  9.         if(substr(string, k, nf) == find) {   
  10.             return k;   
  11.         }   
  12.     }   
  13.     return 0;   
  14. }   
  15.   
  16. {   
  17. x = rindex("afsdfsdffffffx""f",1,2,3);   
  18. print x   
  19. }   


  1. #把数组中的字符串合在一起   
  2. 执行方式   
  3. echo "" | awk -f join.awk   
  4. #! /bin/awk   
  5. function join(array) {   
  6.     n = length(array);   
  7.     if(n >= 1) {   
  8.         s = array[1];   
  9.         for(k=2;k<=n;k++) {   
  10.             s = s "-" array[k];   
  11.         }   
  12.     }   
  13.     return s;   
  14. }   
  15.   
  16. {   
  17. a[1] = "aaa";   
  18. a[2] = "bbb";   
  19. a[3] = "ccc";   
  20. a[4] = "ddd";   
  21. a[5] = "eee";   
  22. print join(a);   
  23. }   

 

 

 

 

 

参考

awk百科

linux awk命令详解

Awk学习笔记

AWK简明教程

awk英文版手册

linux awk内置函数详细介绍

awk man介绍和man strftime介绍


你可能感兴趣的:(Linux)