📓 Archive

AWK

FGJ: Create:2023/06/30 Update: (2024-10-24)

awk (Alfred Aho 、Peter Weinberger 和 Brian Kernighan):
样式扫描和处理语言,它允许您创建简短的程序。读取输入文件,为数据排序,处理数据,对输入执行计算以及生成报表等。其中语法方面有借鉴C语言。

一.语法格式: #

awk 'pattern{action[;action..]}' {filenames}
    
原理:
    调用awk时,依次对文件中匹配的每一行做后面的action,每一对pattern+action用分号[;]隔开。
注意:
    如果一个'' 中没有pattern,默认所有行。action 必须{}包起来
    如果一个'' 中没有action,默认打印本行。
    如果什么都没有,只有'',不做任何处理。
    print,printf:
        print 输出后加一个ORS,而printf标准输出,想换行得加'\n',而这个换行不受awk的ORS控制。

二.常用选项: #

[option]
    -F fs or --field-separator fs                               :指定输入文件拆分符,是一个字符串或正则,如-F:
    -v var=value or --asign var=value                           :赋值一个用户变量
    -f scripfile or --file scriptfile                           :从脚本文件中读取awk命令。
    -mf nnn and -mr nnn                                         :对nnn值设置内在限制,-mf选项限制分配给nnn的最大块数目;-mr选项限制记录的最大数目。这两个功能是Bell实验室版awk的扩展功能,在标准awk中不适用。
    -W compact or --compat, -W traditional or --traditional     :在兼容模式下运行awk。所以gawk的行为和标准的awk完全一样,所有的awk扩展都被忽略。
    -W copyleft or --copyleft, -W copyright or --copyright      :打印简短的版权信息。
    -W help or --help, -W usage or --usage                      :打印全部awk选项和每个选项的简短说明。
    -W lint or --lint                                           :打印不能向传统unix平台移植的结构的警告。
    -W lint-old or --lint-old                                   :打印关于不能向传统unix平台移植的结构的警告。
    -W posix                                                    :打开兼容模式。但有以下限制,不识别:/x、函数关键字、func、换码序列以及当fs是一个空格时,将新行作为一个域分隔符;操作符**和**=不能代替^和^=;fflush无效。
    -W re-interval or --re-inerval                              :允许间隔正则表达式的使用,参考(grep中的Posix字符类),如括号表达式[[:alpha:]]。
    -W source program-text or --source program-text             :使用program-text作为源代码,可与-f命令混用。
    -W version or --version                                     :打印bug报告信息的版本。
  • 三. 使用案例: #

    • 1)简单样例 #

      # echo 'hello this' | awk ''  > 默认不做处理
      # echo 'hello this' | awk '/hello/'  >打印hello this
      # echo 'hello this' | awk '{print $0}'    >打印hello this
      
      # cat test.txt | awk '{if(NR>=20 && NR<=30) print $0}'    > 打印20~30行内容
      
      >test.txt
      I am Poe,my qq is 1234567
      # cat test.txt | awk -F '[ ,]+' '{print $3" "$7'    >Poe 1234567
      
    • 2)BEGIN,END模块 #

      # cat /etc/passwd | awk '{count++;print $0;}END{print "count is",count}'    >统计/etc/passwd的账户人数
      # ll | awk '{size=size+$5}END{print "size is",size/1024,"K"}'   >统计某个文件夹下总字节数
      
    • 3)awk运算符 #

      # awk 'BEGIN{a=5;a+=5;print a}' >5,赋值运算符
      # awk 'BEGIN{a=1;b=2;print (a>2&&b>1,a=1||b>1)}'   >0 1 ,逻辑运算符
      # awk 'BEGIN{a="100testaa";if(a~/100/)print "OK"}'  >OK,正则运算符
      # awk 'BEGIN{a="100testaa"} a~/100/ {print "OK"}'  >等待用户输入
      # awk 'BEGIN{a="11";if(a>=9){print "ok"}}'  >无输出,关系运算符
      # awk 'BEGIN{a=11;if(a>=9){print "ok"}}'    >ok
      # awk 'BEGIN{a;if(a>=b){print "ok"}}'   >ok
      # awk 'BEGIN{a="b";print a++,++a}'  >0 2,算数运算符
      # awk 'BEGIN{a="20b4";print a++,++a}'   >20 22
      # awk 'BEGIN{a="b";print a=="b"?"ok":"err"}' >ok,三目运算符
      # awk 'BEGIN{a="b";print a=="c"?"ok":"err"}' >err
      
    • 4)常用awk内置变量 #

      $0      当前记录
      $1~$n   当前记录的第n个字段
      FS      输入字段分隔符,默认空格
      RS      输入记录分隔符,默认换行符
      NF      当前记录书中的字段个数
      NR      行号,从1开始
      OFS     输出字段分隔符,默认空格
      ORS     输出记录分隔符,默认换行符
      
      >tab.txt
      ww  CC      IDD
      
      # cat tab.txt | awk 'BEGIN{FS="\t+"}{print $1,$2,$3}'  >ww CC IDD
      # cat space.txt | awk -F [[:space:]+] '{print $1,$2,$3,$4,$5}'
      # cat hello.txt | awk -F [" ":]+ '{print $1,$2,$3}'
      # cat hello.txt | awk -F ":" 'NF==8{print $0}' hello.txt
      # ifconfig eth0 | awk -F [" ":]+ 'NR==2{print $4}'
      
      >record.txt
      Jimmy the Weasel
      100 Pleasant Drive
      San Francisco,CA 123456
      
      Big Tony
      200 Incognito Ave.
      Suburbia,WA 64890
      
      >awk.txt
      #!/bin/awk
      BEGIN {
          FS="\n"
          RS=""
      }
      {
          print $1","$2","$3
      }
      
      # awk -f awk.txt recode.txt 
      >Jimmy the Weasel,100 Pleasant Drive,San Francisco,CA 123456
      >Big Tony,200 Incognito Ave.,Suburbia,WA 64890
      
    • 5)awk正则 #

      # cat /etc/passwd | awk '/root/{print $0}'
      # cat /etc/passwd | awk -F: '$5~/root/{print $0}'
      # cat /etc/passwd | awk -F: '$1=="root"{print $0}'
      
    • 6)awk的C语言特性(if,循环和数组) #

      -----------------------------
      {
          if(){
              if(){
                  ...
              }else{
                  ...
              }
          }elseif(){
              ...
          }else{
              ...
          }
      }
      -----------------------------
      {
         count=1 do{
             ...
             if(){
                 break;
             }
         } while()
      }
      -----------------------------
      for(x=1;x<=4;x++){
          ...
          if(){
              continue;
          }
      }
      -----------------------------
      awk中的数组是关联数组,数字索引也会转变为字符串索引,是无序的,有序的得通过下标获得
      -----------------------------
      {
          cities[1]="beijing"
          cities[2]="shanghai"
          cities[“three”]="guangzhou"
          for( c in cities){
              print cities[c]
          }
          print cities["three"];  //也可以
      }
      # netstat -an|awk '/^tcp/{++s[$NF]}END{for(a in s)print a,s[a]}'    
      >LISTEN 9
      >ESTABLISHED 4
      
    • 7)常用字符串函数 #

      #替换
      # awk 'BEGIN{info="this is a test2010test!";gsub(/[0-9]+/,"!",info);print info}'   >this is a test!test!
      
      #查找
      # awk 'BEGIN{info="this is a test2010test!";print index(info,"test")?"ok":"no found";}'   >ok
      
      #匹配查找
      # awk 'BEGIN{info="this is a test2010test!";print match(info,/[0-9]+/)?"ok":"no found";}' >ok
      
      #截取
      # awk 'BEGIN{info="this is a test2010test!";print substr(info,4,10);}'   >s is a tes
      
      #分割
      # awk 'BEGIN{info="this is a test";split(info,tA," ");print length(tA);for(k in tA){print k,tA[k];}}'
      >4
      >4 test
      >1 this
      >2 is
      >3 a
      
      #length(),blength(),tolower(),toupper()...等
      

四.参考: #


comments powered by Disqus