awk学习笔记

    awk是一种模式扫描和处理工具,相对于grep的查找,sed的编辑,它在对数据进行分析生成报表时显得尤为强大。awk通过逐行遍历一个或多个文件的方式,查找模式匹配到的行,而后以指定的分隔符(缺省为空格)进行切片,然后针对切片数据进行处理和分析。事实上,gawk有自己的语言,其本身就相当于一个解释器,允许用户创建简短的程序读取输入文件,对输入数据执行排序、计算以及生成报表操作,甚至可以类似bash shell实现诸如循环、数组、条件判断、函数、变量等功能,进而完成更为复杂的数据分析处理任务。

    Gawk

    gawk(GNU awk)是UNIX awk的GNU版,为方便linux用户使用,通常将/bin/awk以符号链接方式链接到/bin/gawk,以迎合用户的使用习惯。(下文有提到gawk的地方均以awk代替)

    awk的使用方式

       1、命令行方式

          awk [-F field-separator] ‘COMMAND’inputfiles

         //其中COMMAND是awk的执行命令,用来处理数据,[-F field-separator]是可选选项,inputfiles是待处理文件。

         //awk使用中,需要处理的文件,逐行使用分隔符分割成若干个字段,称之为域,分隔符默认是空格,可使用-F选项来指定分隔符

       2、shell脚本模式

          将所需执行的awk命令插入awk脚本文件,然后在首行设置命令解释器为#!/bin/awk,通过键入脚本名的方式调用。

       3、所有awk命令写入到一个单独的文件,当处理同一类文件需求时,使用awk -f awk-script inputfiles调用之,其中awk-script指awk脚本。

    awk的基本语法    

       awk [OPTION] 'program' FILE1 FILE2…

       program:PATTERN{ACTION STATEMENT} //program由语句组成,各语句之间使用;隔开,整个program要用单引号引起来

       OPTION:选项 

             -F:指定分割符

                例,指定分隔符为“:”,打印出系统上各用户名和morenshell

                # awk -F: '{print $1,$7}' /etc/passwd

               blob.png

             -v:指定变量

                例,通过-v选项指定变量a=hello awk 然后将其打印出来

                # awk -v a="hello awk" '{print a}'

               blob.png

               另外,也可以通过特殊模式BEGIN(模式下述)来指定变量,如上例,也可以这样写

               # awk 'BEGIN{a="hello awk"}{print a}'

               blob.png

             -f:指定脚本文件

    awk变量

       awk的变量,可分类为内置变量和自定义变量

       1、内置变量

         blob.png

       2、自定义变量

         自定义变量有两种方式(上文基本语法中已有示例,此处不再赘述),但是,在脚本中仍然可以声明变量。

         (1)、awk -v VARIABLE_NAME VARIABLE_VALUE 'program' inputfiles 

         (2)、awk 'BEGIN{VARIABLE_NAME VARIABLE_VALUE}ACTION STATEMENT}' inputfiles  

       3、变量使用示例

         (1)、FS输入分隔符,默认为空格

           例如,默认分隔符使用awk提取/etc/inittab中的“#”,如下图可以看到,如果以空格分割,第一个域即为#(忽略最后一行)

           blob.png

           # awk '{print $1}' /etc/inittab //效果如下(最后一行请忽略) 

           blob.png

           以“:”为分隔符,提取系统中用户名以及用户默认

           # awk -v FS=":" '{print $1,$7}' /etc/passwd

           blob.png

         (2)、输出分隔符,默认为空格(如上图上例显示结果),接上例,以:为输出分隔符显示输出结果

           # awk -v FS=":" -v OFS=":" '{print $1,$7}' /etc/passwd 

           blob.png

         (3)、NR和FNR

           显示/etc/{inittab,passwd}所有内容以及行数

           # awk '{print NR,$0}' /etc/{inittab,passwd}//看下图,行数不分开计数

           blob.png

           # awk '{print FNR,$0}' /etc/{inittab,passwd}//看下图,使用FNR单独计数行数

           blob.png

           # awk 'BEGIN{print "filename","alone_lines","unit_lines"}{print FILENAME,NR,FNR}' /etc/{passwd,inittab,group}//还可以这样写来分别显示总行号和单独行号,此处不再贴图

         (4)、ARGC显示参数个数

           # awk -F: '{print $1}END{print ARGC}' /etc/passwd //如下图,显示参数为二(经验证,貌似program也被识别成为一个参数,再加上后面的文件故为2个参数?) 

           blob.png

    awk的模式

       1、Regular Expression 正则表达式

         如其名,使用正则表达式匹配模式,在需要注意的是,在awk中使用正则表达式,匹配字符串要使用双斜线括起来,而后匹配到的行将被切片并分析处理,反之将略过。

       取出/etc/passwd中包含root的行并打印出用户名和默认shell

       # awk -F: ‘/root/ {print $1,$7}' /etc/passwd 

       blob.png

       2、Expression 表达式,当表达式的值为真(非零或非空)的行被匹配,仅处理匹配到的行

       # awk -F: '$3>=500{print $1,$2,$3}' /etc/passwd 

       blob.png

       在此列出awk的常用操作符  

      blob.png

      blob.png

      如果模式自身是=,要写为/=/

     blob.png

     blob.png

     blob.png

     条件表达式:

       selector?if-true-express:if-false-express 只能是表达式不能使语句

       条件表达式中,“:”两侧仅允许使用表达式而不能使用语句

       例

       # awk -F: '$3>=500?utype="common user":utype="admin or system user"{print $1 "is" utype} /etc/passwd 

       blob.png

       3、range行范围,有两种方式来定义此范围

        (1)、pattern1,pattern2

        从匹配到pattern1的行开始到匹配到pattern2的行为知,此范围的行被awk action处理

        # awk 'NR==1,NR==10{print $1,$3,$7} /etc/passwd 

        blob.png  

       4、特殊模式BEGIN和END

      (1)、BEGIN在读取任何输入之前执行一次语句

        # awk 'BEGIN{FS=":";OFS=":"}/root/{print $1,$3,$7} /etc/passwd 

       blob.png

      (2)、END在读取所有输入之后执行一次语句 

       # awk 'BEGIN{FS=":";OFS=":"}/root/{print $1,$3,$7}END{print "The end!"}' /etc/passwd

       blob.png

       5、空模式

         如果不指定模式则匹配文件中的所有行

    awk重定向       

       1、输出重定向

         awk可以使用shell的重定向符重定向输出,同样>代表覆盖式输出,>>代表追加。

         覆盖式重定向

         blob.png

         追加重定向效果

         blob.png

       2、输入重定向

        输入重定向需用到getline函数。getline从标准输入、管道或者当前正在处理的文件之外的其他输入文件获得输入。它负责从输入获得下一行的内容,并给NF,NR和FNR等内建变量赋值。如果得到一条记录,getline函数返回1,如果到达文件的末尾就返回0,如果出现错误,例如打开文件失败,就返回-1,可以结合到while等流控制语句使用。 

       通过例子说明输入重定向用法

       (1)、awk 'BEGIN{"date" | getline d; print d}'

        blob.png

         getling函数读取date命令的输出结果并将其赋值给自定义变量d,然后打印变量d

       (2)、awk 'BEGIN{"date" | getline d; split(d,mon); print mon[3]}'

        blob.png

        getine函数读取date命令输出的结果并赋值给自定义变量d,split函数将变量d转化为数组mon,然后打印数组mon的第三个元素。

       (3)、awk 'BEGIN{while("ls" | getline) print}'

        blob.png

       getline函数读取ls命令的输出结果而后打印显示

    awk之print和printf

       1、print

       用法:print item1,item2….

       要点:

        (1)、各item之间使用,号隔开,输出时默认以空格分隔

        (2)、输出的item可以是字符串或数值、当前分隔出来的域(字段,如$1)、变量或awk的表达式,数值会隐式转换为字符串输出。

        (3)、print后面的item项可以省略,此时相当于打印$0即整行内容;print ""表示打印空白行。

           例:

           # awk 'BEGIN{print "line1","line2","line3"}'

           blob.png

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

           blob.png

       2、printf

        用来格式话打印输出内容

        (1)、格式:

         printf format,item1,ietm2,…

        (2)、要点

          printf需要指定format;

          format用于指定后面每个item的格式;

          printf不能自行换行,如需换行需给定\n;

          使用修饰符可以使输出格式更加美观。

        (3)、format的格式指示符,以%开始,后跟一个字符

          %c:显示字符的ASCII吗

          %d,%i:十进制整数

          %e,%E:科学计数法显示数值

          %f:显示浮点数本身

          %g,%G:以科学计数法格式或浮点数显示数值

          %s:显示字符串

          %u:显示无符号整数

          %%:显示%自身

         修饰符

          #:字段的显示宽度

          .#:取值精度

          -:左对齐

          =+:显示数值的符号

        (4)、例:

          取出系统用户的用户名和默认shell,要求用户名左对齐,占用15个字符,字符串显示;要求默认shell左对齐,占用20字符,字符串显示

          awk -F: ‘{printf "%-15s %-20s\n",$1,$7}' /etcpasswd 

         blob.png

         使用显示浮点数自身(%f)的方式显示,会自动补全精度,长于精度部分将会执行四舍五入

         # awk 'BEGIN{printf "%f\n",3.15}'

         blob.png

         当使用数字来定义字段占用字符长度时,要放在其它修饰符前面;小数点后面的数字代表精度

         # awk 'BEGIN{printf "%-15.2\n",3.15}'

         blob.png

    awk之action

        1、常见action

         (1)、表达式  Expression

         (2)、控制语句 Control statements

         (3)、组合语句 Commpound statments      

         (4)、输入语句 Input statments

         (5)、输出语句 Output statements

       2、awk常见控制语句以及使用示例

         (1)、if-else语句 格式:if (condition) {then body} else {else body}                

            # awk -F: '{if($3>=500{print $1 "is a common user"} else {print $1 "is admin or systemuser"}' /etc/passwd 

            uid号大于等于500的显示为普通用户,小于500的显示为管理员或系统用户。

            blob.png

           # awk -F: '{if(NF>=8){print}}' /etc/inittab 

            打印显示以冒号切割形成字段大于等于8的行

            blob.png

         (2)、while语句 格式: 格式:while (condition) {while body}

            awk '{i=1;while(i<=NF){printf "%s ",$i;i+=2}; print ""}' /etc/inittab 

            打印输出/etc/inittab中的奇数字段

            blob.png        

          打印出字符大于等于6的字段

          # awk '{i=1;while(i<=NF{if(length($i<=6){print $i};i++}}' /etc/inittab 

          blob.png                      

        (3)、do-while循环 格式:格式:do {do-while body} while (condition)

                             # awk 'BEGIN{sum=0;i=0;do{sum+=i;i+=}while{i<=100};print sum;}'

                            求和1-100

         blob.png

        (4)、for循环 格式:for (variable assignment; condition; iteration process) {for body}

                            # awk '{for(i=1,i<=NF,i+=2){printf "%s ",$1};print ""}' /etc/inittab

                          打印出/etc/inittab中的每行的奇数字段

                          blob.png

                          for循环还可以用来遍历数组 格式:for (i in array) {for body}

                          # awk 'BEGIN{"date" | getline d; split(d,test);for (i in test) print test[i]}'

                          blob.png

                          break 用于在满足条件的情况下跳出循环;continue用于在满足条件时忽略后面的语句,直接返回循环的顶端

                     (5)、next提前结束本行处理,进入下一行处理

                          取uid为奇数的用户和uid

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

                          blob.png

                   (6)、数组

                          关联数组

                      array[index-expression]index-expression:可以使用任意字符串;如果某数组元素事先不存在,那么在引用时,awk会自动创建次元素并将其初始化为空串;因此,要判断某数组是否存在某元素,必须使用“index in array”这种格式A[first]="hello awk"print A[second]要遍历数组中的每一个元素,需要使用如下特殊结构:for (var in array) {for body}期中var会遍历array的索引,而非元素的值

                   (7)、awk的内置函数 split(string,array[,fieldsep[,seps]])能够将string标示的字符串以fieldsep为分隔符进行切片,并切片后的结果保存至array为名的数组中;数组下表从1开始

         # awk 'BEGIN{split("root:x:0:0",user,":");for (i in user) print user[i]}'

        blob.png

      由于本人水平有限,awk的使用先总结到这里吧,在以后的使用中再深入研究。

    

                   



 


 

                    

  

       

    

原创文章,作者:Silently,如若转载,请注明出处:http://www.178linux.com/6553