-F fs   fs指定输入分隔符,fs可以是字符串或正则表达式,如-F:
-v var=value   赋值一个用户定义变量,将外部变量传递给awk
-f scripfile  从脚本文件中读取awk命令
-m[fr] val   对val值设置内在限制,-mf选项限制分配给val的最大块数目;-mr选项限制记录的最大数目。这两个功能是Bell实验室版awk的扩展功能,在标准awk中不适用。

1.1 模式

模式可以是以下任意一个:

  • /正则表达式/:使用通配符的扩展集。
  • 关系表达式:使用运算符进行操作,可以是字符串或数字的比较测试。
  • 模式匹配表达式:用运算符~(匹配)和~!(不匹配)。
  • BEGIN语句块、pattern语句块、END语句块:参见awk的工作原理
  • 1.2 操作

    操作由一个或多个命令、函数、表达式组成,之间由换行符或分号隔开,并位于大括号内,主要部分是:

  • 变量或数组赋值
  • 控制流语句
  • 1.3 基本结构

    awk 'BEGIN{ print "start" } pattern{ commands } END{ print "end" }' file
    

    一个awk脚本通常由:BEGIN语句块、能够使用模式匹配的通用语句块、END语句块3部分组成,这三个部分是可选的。任意一个部分都可以不出现在脚本中,脚本通常是被单引号或双引号中,例如:

    awk 'BEGIN{ i=0 } { i++ } END{ print i }' filename
      
  • 第一步:执行BEGIN{ commands }语句块中的语句;
  • 第二步:从文件或标准输入(stdin)读取一行,然后执行pattern{ commands }语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。
  • 第三步:当读至输入流末尾时,执行END{ commands }语句块。
  • BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中。END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块。pattern语句块中的通用命令是最重要的部分,它也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块。

    1.4 打印

    当使用不带参数的print时,它就打印当前行,当print的参数是以逗号进行分隔时,打印时则以空格作为定界符。在awk的print语句块中双引号是被当作拼接符使用,例如:

    echo | awk '{ var1="v1"; var2="v2"; var3="v3"; print var1,var2,var3; }' 
    v1 v2 v3
    

    双引号拼接使用:

    echo | awk '{ var1="v1"; var2="v2"; var3="v3"; print var1"="var2"="var3; }'
    v1=v2=v3 { }类似一个循环体,会对文件中的每一行进行迭代,通常变量初始化语句(如:i=0)以及打印文件头部的语句放入BEGIN语句块中,将打印的结果等语句放在END语句块中。
    

    1.5 awk内置变量(预定义变量)

    说明:[A][N][P][G]表示第一个支持变量的工具,[A]=awk、[N]=nawk、[P]=POSIXawk、[G]=gawk

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

    2. 使用示例

    将外部变量值传递给awk

    借助-v选项,可以将外部值(并非来自stdin)传递给awk:
    VAR=10000
    echo | awk -v VARIABLE=$VAR '{ print VARIABLE }'
    另一种传递外部变量方法:
    var1="aaa"
    var2="bbb"
    echo | awk '{ print v1,v2 }' v1=$var1 v2=$var2
    

    统计文件中的行数

    awk 'END{ print NR }' filename
    

    以上命令只使用了END语句块,在读入每一行的时,awk会将NR更新为对应的行号,当到达最后一行NR的值就是最后一行的行号,所以END语句块中的NR就是文件的行数。

    当记录行号除以2余1,就跳过当前行。下面的print NR,$0也不会执行。下一行开始,程序有开始判断NR%2值。这个时候记录行号是:2 ,就会执行下面语句块:’print NR,$0’

    分析发现需要将包含有“web”行进行跳过,然后需要将内容与下面行合并为一行:

    cat text.txt
    web01[192.168.2.100]
    httpd            ok
    tomcat               ok
    sendmail               ok
    web02[192.168.2.101]
    httpd            ok
    postfix               ok
    web03[192.168.2.102]
    mysqld            ok
    httpd               ok
    awk '/^web/{T=$0;next;}{print T":t"$0;}' test.txt
    web01[192.168.2.100]:   httpd            ok
    web01[192.168.2.100]:   tomcat               ok
    web01[192.168.2.100]:   sendmail               ok
    web02[192.168.2.101]:   httpd            ok
    web02[192.168.2.101]:   postfix               ok
    web03[192.168.2.102]:   mysqld            ok
    web03[192.168.2.102]:   httpd               ok
    

    获取命令输入

    执行linux的date命令,并通过管道输出给getline,然后再把输出赋值给自定义变量out,并打印它:

    awk 'BEGIN{ "date" | getline out; print out }' test
    

    分割字符串

    执行shell的date命令,并通过管道输出给getline,然后getline从管道中读取并将输入赋值给out, split函数把变量out转化成数组mon,然后打印数组mon的第二个元素:

    awk 'BEGIN{ "date" | getline out; split(out,mon); print mon[2] }' test 忽略输入文件。
    

    输出到文件

    awk中允许用如下方式将结果输出到一个文件:

    echo | awk '{printf("hello word!n") > "datafile"}'
    echo | awk '{printf("hello word!n") >> "datafile"}'
    

    设置字段定界符

    默认的字段定界符是空格,可以使用-F “定界符” 明确指定一个定界符:

    awk -F: '{ print $NF }' /etc/passwd
    awk 'BEGIN{ FS=":" } { print $NF }' /etc/passwd
    在BEGIN语句块中则可以用OFS=“定界符”设置输出字段的定界符。
    

    打印某行某列

    brctl show | awk 'NR==2 { print $2 }'
    

    每一行累加

    seq 5 | awk 'BEGIN{ sum=0; print "总和:" } { print $1"+"; sum+=$1 } END{ print "等于"; print sum }' 
    
    [root@hhb-kvm ~]# cat ./awkif
    #!/bin/bash
    awk '{
            if ($3 >=30 )
                    print "User", $1,$2, "is more than 30 years old.";
    		else if ($3 >= 25)
    				print "User", $1,$2, "is more than 25 years old.";
                    print "User", $1,$2, "is less than 25 years old.";
    }'  ./users.tst
    [root@hhb-kvm ~]# cat users.tst
    Huang Haibin   31
    Ying Weihong   28
    Huang Yuman    3
    

    while

    awk 'BEGIN{
    test=100;
    total=0;
    while(i<=test){
      total+=i;
    print total;
    
    awk 'BEGIN{
    for(k in ENVIRON){
      print k"="ENVIRON[k];
    awk 'BEGIN{
    total=0;
    for(i=0;i<=100;i++){
      total+=i;
      break;
    print total;
    
    awk 'BEGIN{ 
    total=0;
    do {total+=i;i++;} while(i<=100)
      print total;
    
    awk 'BEGIN{
    for(i=1;i<=9;i++){
      for(j=1;j<=9;j++){
        tarr[i,j]=i*j;
    for(m in tarr){
      split(m,tarr2,SUBSEP); print tarr2[1],"*",tarr2[2],"=",tarr[m];
    awk 'BEGIN{tB["a"]="a1";tB["b"]="b1";if(tB["c"]!="1"){print "no found";};for(k in tB){print k,tB[k];}}' 
    no found
    awk 'BEGIN{info="it is a test";split(info,tA," ");for(k in tA){print k,tA[k];}}'
    4 test
    
    awk 'BEGIN{tstamp=mktime("2001 01 01 12 12 12");print strftime("%c",tstamp);}'
    2001年01月01日 星期一 12时12分12秒
    awk 'BEGIN{tstamp1=mktime("2001 01 01 12 12 12");tstamp2=mktime("2001 02 01 0 0 0");print tstamp2-tstamp1;}'
    2634468
    求2个时间段中间时间差,介绍了strftime使用方法
    awk 'BEGIN{tstamp1=mktime("2001 01 01 12 12 12");tstamp2=systime();print tstamp2-tstamp1;}' 
    308201392
    

    http://man.linuxde.net/awk
    http://www.runoob.com/linux/linux-comm-awk.html
    https://www.ibm.com/support/knowledgecenter/zh/ssw_aix_72/com.ibm.aix.cmds1/awk.htm

    The site is producted by @Haibin