文本处理三剑客之awk

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了文本处理三剑客之awk相关的知识,希望对你有一定的参考价值。

文本处理三剑客之awk

   awk:

     报告生成器,格式化文档输出;

   awk(gawk):pattern scanning and processing language

      格式:awk  [options...]  'program'  file

     program: [/PATTERN/]{ACTION statement;...}

      PATTERN:决定动作语句何时触发以及通过什么事件来触发(BEGIN/END);

      ACTION statement:对数据进行特定的处理,通常放在{}中(print/printf);


  基本概念:

   分隔符(输入分割符,输出分隔符)

      输入分割符:

       awk对数据进行处理时,会根据特定的标识符对数据进行分段处理,该标识符称为输入分隔符(默认为空白字符);

      输出分隔符:

       awk在处理完数据后,会以特定标识符对各字段进行输出;

   

   记录:由换行符分割的数据中的一行,称为一条记录,通常用$0表示;

   字段:经过分隔符分割后的每一个数据分段(field),通常用$N表示(N为除0外的数字);



  awk的工作原理:

         1):首先执行Begin{action statement}语句块中的语句;

         2):其次,从文件或标准输入中读取一行,根据Pattern匹配的结果执行action的内容,重复此操作,直到完毕;

         3):最后,执行End{action statement}语句块中的语句;

   

     注意:

         1)begin语句在awk处理数据前执行,常用于生成表头(该语句可省略)

         2)end语句在awk处理完所有数据后执行,用于数据汇总(该语句可省略)

         3)Pattern语句是最重要的部分,不可省略,但action可省略,默认执行print操作;

         4)awk在执行Pattern语句块时,默认循环遍历数据中的各记录;

     


     常用选项:

        -f:--file program-file:从指定文件中加载program语句块;

        -F:--filed-sparator fs:指定字段的输入分隔符;

        -V:--assign var=value:用于声明自定义变量并为其赋值;



     awk的常用用法:

       1.变量:(内置变量,自定义变量)

          

          内置变量:

             FS:input field separator:输入字段分割符,默认为空白字符;                   

             OFS:output field separator:输出字段分隔符,默认为空白字符;

             例:

             ~]# awk -v FS=':' -v OFS=':' '{print $1,$2}' /etc/group

      

             RS:输入记录分隔符,默认为换行符(即使定义了记录分割符,原有的换行符依旧有效);

             ORS:输出记录分隔符,默认为换行符(即使定义了记录分割符,原有的换行符依旧有效);

             例:

             ~]# awk -v RS=':'   '{print $1,$2}' /etc/group


             NF:每一行字段的总数;

             例:

             ~]# awk -F: '{print NF}' /etc/group


             NR:列出文件行的总行号;

             例:

             ~]# awk -F: '{print NR}' /etc/group


             FNR:对不同的文件统计文件行的行号;

             例:

             ~]# awk -F: '{print FNR}' /etc/group /etc/passwd

             FILENAME:当前正在被使用的文件的文件名;

             例:

            ~]# awk -F: 'END{print FILENAME}' /etc/group /etc/passwd

  

       ARGC:命令行中参数数量(不包括Option中和Program中的参数)

             例:

             ~]# awk -F: 'END{print ARGC}' /etc/group /etc/passwd  /etc/fstab


             ARGV:由命令行所有参数构成的数组

             例: 

             ~]# awk -F: 'END{print ARGV[2]}' /etc/group /etc/passwd  /etc/fstab

         自定义变量:

             定义方式:-v var_name

             例子:

              # awk -v var='你好' -F: '{print $1,":",var}' /etc/passwd

                

        

       2.常用的action:

           print:

             格式:print item1,item2....

             注意:1)各item之间需使用","进行分割  

                   2)item可以是字符串,数字,变量,当前记录中的字段,也可是awk表达式(省略则输出整行)

             例:

             ~]# awk -F: '{print $1,$3,$6}' /etc/passwd


           printf:format and print ,以特定的格式输出结果;

             格式; ;printf "FORMAT" item1,item2....

             注意:1)必须给出合适的输出格式

                   2)默认不自动换行,需给出"\n"

                   3)FORMAT中需为后面的每个item指定格式化符号;

  

             常用的FORMAT:

                   %c:以ACSII码表中的内容显示字符信息;

                   %d,%i:显示十进制整数

                   %e,%E:以科学记数法显示数字,浮点类型;

                   %f,%F:显示十进制数字的浮点形式

                   %g,%G:以科学记数法显示浮点数字

                   %v:显示无符号十进制数字

                   %s:显示字符串

                   %x,%X:显示无符号的十六进制数

                   %%:显示%

      

                

                    修饰符:

                  #[.#]:第一个数字用来控制显示宽度;第二个数字表示小数点的精度;

                  如:%5s, $8.3f

                  -:表示采用左对齐方式显示;默认是右对齐;

                  +:显示数字的正负符号;


                 示例:

                  技术分享图片



        3.操作符:

             算术运算操作符:

                  双目运算符:

                     x+y, x-y, x*y, x/y, x^y, x%y

                  单目运算符:

                     -x:将正整数转换为负整数;

                     +x:将字符串转换为数值;


             字符串操作符:

                  无任何操作符号时,即为字符串连接操作;


             赋值操作符:

                  =, +=, -=, *=, /=, ^=, %=,++, --


             比较操作符:

                  ==, !=, >, >=, <, <=


             模式匹配操作符:

                 ~:操作符左侧的字符串是否能够被右侧的PATTERN所匹配;

                 !~:操作符左侧的字符串是否不能被右侧的PATTERN所匹配;

                        例:

                        ~]# awk -F: '$1~/root/{print $0}' /etc/group




            逻辑运算操作符:

                &&

                ||

                |

                        例:

                        ~]# awk -F: '$3>100&&$3<200{print $0}' /etc/group



            条件表达式:

                selector(condition)?if-true-expression:if-false-expression

                       例:

                       ~]# awk -F: '{$3>100?usertype="common":usertype="super";printf "%-20s: %-5s\n",$1,usertype}' /etc/passwd



       4.PATTERN部分:

           1) empty:空模式,不加区分地处理文件的每一行;

           2) [!]/REGEXP/:仅处理[不]能被PATTERN匹配到的行;

              例:

              ~]# awk -F: '/^r/{print $0}' /etc/passwd


           3) 关系表达式:

              $3>=1000

              $NF~/bash/

           4) 行域,行范围:

                 关系表达式的逻辑运算:FNR>=10&&FNR<==20

                 例:

                 ~]# awk 'NR>=15&&NR<=20{print NR,$0}' /etc/passwd


                /REGEXP1/,/REGEXP2/:

                  从被REGEXP1匹配的行开始,直到被REGEXP2匹配的行结束,这期间的所有行;凡是属于此类的匹配结果,有多少组就显示多少组;

                 示例:

                   ~]# awk -F: '/^r/,/^a/{print NR,$0}' /etc/passwd


           

           5) BEGIN/END模式:

             BEGIN{}

              仅在开始处理文件中的第一行文本数据之前执行一次的语句块;多用于输出特定格式的表头信息;

             例:

             ~]# awk -F: 'BEGIN{printf "%20s %10s %20s\n","USERNAME","USERID","SHELL"}NR>=15&&NR<=20{printf "%20s %10s %20s\n",$1,$3,$7}' /etc/passwd


             END{}

             仅在文本处理完成但awk命令尚未退出时执行一次的语句块;多用于数据信息的汇总;

             例:

             ~]# awk -F: 'BEGIN{printf "%20s %10s %20s\n","USERNAME","USERID","SHELL"}NR>=15&&NR<=20{printf "%20s %10s %20s\n",$1,$3,$7}END{print "-------\n",NR " users"}' /etc/passwd


           注意:

           1) BEGIN语句块,PATTERN语句块和END语句块的顺序,通常来讲是:BEGIN{}PATTERN{}END{}

           2) BEGIN语句块和END语句块是可选的,但PATTERN语句块必须给出;


        

      5.常用的ACTIONS

        1) 表达式(Expression)

        2) 组合语句(Compound Statements)

        3) 输入语句(Input Statements)

        4) 输出语句(Output Statements)

        5) 控制语句(Control Statements)


    6.控制语句:

       if (condition) statement [ else statement ]

       while (condition) statement

       do statement while (condition)

       for (expr1; expr2; expr3) statement

       for (var in array) statement

       break

       continue

       exit [ expression ]

      switch (expression) { case value|regex : statement ... [ default: statement ] }

      next


                

       1) if ... else:

         语法:

         if (condition) statement [ else statement ]

         使用场景:对awk取得的整行或某个字段做条件判断;


       示例:

         ~]# awk -F: '{if($3>=1000){print "CommonUser:",$1}else{print "Sysuser:",$1}}' /etc/passwd

         ~]# awk fstab'/^[^#]/{if(NF==6){print}}' /etc/passwd

          分析磁盘上各个文件系统的空间利用率:

          ~]# df -h | awk -F% '/^\/dev/{print $1}' | awk '{if($NF>=80){print $1}}'


      2) while循环:

         语法:

         while (condition) statement

         使用场景:

            a.对一行内的多个字段逐一做相同或类似的操作处理时使用;

            b.对数组中的各数组元素做遍历处理时使用;


          while循环的特点:条件为真,进入循环;一旦条件为假,则退出循环;


        例:

         ~]# awk '{i=1;while(i<=NF){print $i,length($i);i++}}' testfile


       3) do ... while语句:

         语法:

         do statement while (condition)


         意义:与while循环相同,但statement语句段至少被执行一次;


       4) for循环:

     语法:

       for (expr1; expr2; expr3) statement

       expr1:variable assignment,变量赋初值;

       expr2:circle condition,循环条件判断;

       expr3:interation process,变量值修正方法;


       示例:

        ~]# awk '{for(i=1;i<=NF;i++){print $i,length($i)}}' testfile


         for (var in array) statement


      5) switch ... case语句

        语法:

       switch (expression) { case value|regex:statement;case value2|regex2:statement;... [ default: statement ] }


       使用场景:

       用于进行字符串比较判断;


    6) break和continue语句:

       break [n]

       continue


       注意:其使用场景是行内多个字段间做循环时的循环控制方式;

      例:

          ~]# awk '{for(i=1;i<=NF;i++){if(length($i)<5){continue}else{print $i,length($i)}}}' testfile


   7) next语句:

      在awk处理数据时,提前结束对当前行的处理,而直接开始处理下一行;


      例:

      ~]# awk -F: '{if($3%2==1){next}else{print $1,$3}}' /etc/passwd

          

    

    8.数组——Array

用户自定义的数组,一般使用关联数组:array_name[index_expression]

        注意:

1) index_expression可以使用任意的字符串,但字符串必须放在双引号中;

2) 支持弱变量数组,即:如果某数组元素事先不存在,当引用该元素时,awk会自动创建此元素,并为此元素赋"空字符串"作为其初始值;


    示例:

       ~]# awk 'BEGIN{name["leader"]="zhangsan";name["mem1"]="lisi";name["mem2"]="bob";print "Leader:",name["leader"],"Member:",name["mem1"],name["mem2"]}'


        ~]# awk 'BEGIN{name["leader"]="zhangsan";name["mem1"]="lisi";name["mem2"]="bob";for(i in name){print name[i]}}'


查看当前系统上所有服务的不同TCP状态的连接数量的统计:

~]# netstat -nalt | awk '/^tcp\>/{state[$NF]++}END{for(stat in state){printf "%15s: %-10d\n",stat,state[stat]}}'


用于统计本服务器web站点的每个用户的请求数值:

~]# awk '{ipaddr[$1]++}END{for(ip in ipaddr){print ip,ipaddr[ip]}}' /var/log/httpd/access_log


用于统计本服务器web站点的UV值:

~]# awk '{ipaddr[$1]++}END{for(ip in ipaddr){print ip,ipaddr[ip]}}' /var/log/httpd/access_log | wc -l


    9.函数:

内建函数:

  数值函数:Numeric Functions

rand():返回一个介于0到1之间的随机数;

sqrt():对于指定的数值进行开二次方;


  字符串函数:String Functions

length():计算给定字符串的长度;

gsub(r, s [, t]):以r表示的模式来查找t表示的字符串中能够被匹配的内容,并将所有出现的内容替换成s表示的内容;

split(s, a [, r [, seps] ]):以seps作为分隔符,利用r表示的模式进行匹配,将s代表的字符串分割之后,保存在a表示的数组中;


  自定义函数:

function name(parameter list) { statements }





























     

    

以上是关于文本处理三剑客之awk的主要内容,如果未能解决你的问题,请参考以下文章

文本处理三剑客之gawk

文本处理三剑客之awk(原创)

文本处理三剑客之AWK

文本处理三剑客之awk

文本处理三剑客之awk(报告生成器)

Linux系统文本处理三剑客之awk