📓 Archive

  • Pricing
  • Chess
  • Syntax
  • AWK

    FGJ: Create:2023/06/30 Update: (2025-02-12)

    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