文本处理三剑客之awk

1. 首先简要总结一些文本处理三剑客:

      grep族:文本过滤工具

      sed:行编辑工具

2. 下面就来看看awk是什么?

   awk现在linux上用的是GNU awk即gawk ,现在centos系统上awk是gawk的一个符号链接文件。那么awk究竟在centos系统上是用来做什么的呢?awk就是一个报告生成器,格式化文本输出的工具。

3. 学习awk对有什么帮助呢?

   学习awk我们可以轻松的对我们想要处理的文本进行查看等,方便我们解决问题。

4. gawk的基本用法:

  gawk - pattern scanning and processing language模式扫描及处理语言


  语法: gawk  [options ] ‘program’ file ...

    详说其中:

  4.1 [options]:

        -F指明输入时的字段分隔符

        -v VAR=VALUE 主要用于实现自定义变量


  4.2 program:PATTERN{ACTION STATEMENTS}

            语句之间用分号分隔

            内建命令: print,printf


5. 选项中的使用的变量:

  5.1 变量  (注:awk中自己的变量是不能加$符的,跟bash是不一样的)

      内建变量:

          FS:input field seperator 输入字段分隔符,默认为空白字符

          此等同于-F分隔符

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

eg:

[root@bucktan ~]# tail -2 /etc/fstab| awk -v OFS=':' '{print $1,$3}'

sysfs:sysfs

proc:proc

[root@bucktan ~]# tail -2 /etc/fstab

sysfs                   /sys                    sysfs   defaults        0 0

proc                    /proc                   proc    defaults        0 0

[root@bucktan ~]# tail -2 /etc/passwd| awk -v FS=':' '{print $1,$3}'

apple 2000

zabbix 495


           RS:input record sepereator指定输入时的换行符

           ORS:output record sepereator指定输出时的换行符

eg:

[root@bucktan ~]# awk -v RS=' ' -v ORS='##' '{print}' /etc/passwd

root:x:0:0:root:/root:/bin/bash

bin:x:1:1:bin:/bin:/sbin/nologin

daemon:x:2:2:daemon:/sbin:/sbin/nologin

adm:x:3:4:adm:/var/adm:/sbin/nologin

lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

sync:x:5:0:sync:/sbin:/bin/sync

shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

halt:x:7:0:halt:/sbin:/sbin/halt

mail:x:8:12:mail:/var/spool/mail:/sbin/nologin

uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin

operator:x:11:0:operator:/root:/sbin/nologin

games:x:12:100:games:/usr/games:/sbin/nologin

gopher:x:13:30:gopher:/var/gopher:/sbin/nologin

ftp:x:14:50:FTP##User:/var/ftp:/sbin/nologin

nobody:x:99:99:Nobody:/:/sbin/nologin

dbus:x:81:81:System##message##bus:/:/sbin/nologin

  注意看其中的#号        

           NF:number of field 统计每一行字段的数量

              {print NF}  

              {print $NF}:打印最后一个字段

              ~]# awk '{print NF}' /etc/passwd

eg:

[root@bucktan ~]# awk -F: '{print $NF}' /etc/passwd

           

           NR:number of record打印每一行的行号,但事实上统计的是文件的总体行数         

           FNR:各文件分别计数,计行数

           FILENAME:当前正在处理的文件名

           ARGC:命令行参数的个数

           ARGV:数组,保存的是命令行所给定的各参数

                ARGV[0]:第一个参数

             。。。。。

eg:

[root@bucktan ~]# awk 'BEGIN{print ARGV[0]}' /etc/passwd /etc/fstab

awk

[root@bucktan ~]# awk 'BEGIN{print ARGV[1]}' /etc/passwd /etc/fstab

/etc/passwd


注:BEGIN的作用是实现不会对每一行打印的结果。如果没有BEGIN则每一行都要显示一个打印的值


  5.2自定义变量:

        (1):-v var=value    变量名区分字符大小写

        (2):在program中直接定义

eg:

[root@bucktan ~]# awk -v abc='love you' '{print abc}’ /etc/passwd

另一种实现:

[root@bucktan ~]# awk 'BEGIN{abc="love you"; print abc} '

love you

       

       语法: gawk  [options ] ‘program’ file ...

       program:PATTERN{ACTION STATEMENTS}

      

6. 其中的內建命令

  6.1:print(用于{ACTION STATEMENTS}中)

        print iterm1,iterm2,。。。

       要点:1):逗号为分隔符,但在输出时显示的是空白符而非逗号

            (2) :输出的各iterm可以是字符串、数值、当前记录的字段、变量或awk的表达式

           (3):如果省略iterm,相当于print$0 

eg:      

[root@bucktan ~]# tail -5 /etc/passwd | awk -F: '{print "hehe:"111$1,$3}'

hehe:111tcpdump 72

hehe:111bucktan 500

hehe:111centos 496

hehe:111apple 2000

hehe:111zabbix 495 

[root@bucktan ~]# tail -2 /etc/passwd | awk -F: '{print}'

apple:x:2000:2000::/home/apple:/bin/bash

zabbix:x:495:492:Zabbix Monitoring System:/var/lib/zabbix:/sbin/nologin                            

    

  6.2 printf命令

         printf - format and print 

       

      格式化输出:printf FORMAT iterm1,iterm2,...

      要点: (1):FORMAT:必须要给出

          (2):不会自动换行,需要显示给出换行控制符才知道哪行

          (3):FORMAT中需要分别为后面的每个iterm指定一个格式化符号


        格式符:

         %c:显示字符的ASCII码

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

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

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

         %s:显示字符串

         %u:无符号整数

        %%:显示%自身

  样式一              

 [root@bucktan ~]# awk -F: '{printf "%s",$1}' /etc/passwd

rootbindaemonadmlpsyncshutdownhaltmailuucpoperatorgamesgopherftpnobodydbususbmuxdvcsarpcrtkitavahi-autoipdabrtrpcusernfsnobodyhaldaemongdmntpapache

  样式二

  [root@bucktan ~]# awk -F: '{printf "%s\n",$1}' /etc/passwd

root

bin

daemon

adm

lp

样式三

[root@bucktan ~]# awk -F: '{printf "username: %s\n",$1}' /etc/passwd

username: root

username: bin

username: daemon

username: adm

username: lp

样式四

[root@bucktan ~]# awk -F: '{printf "username: %s,  userid: %s\n",$1,$3}' /etc/passwd

username: root,  userid: 0

username: bin,  userid: 1

username: daemon,  userid: 2

username: adm,  userid: 3

username: lp,  userid: 4

username: sync,  userid: 5

username: shutdown,  userid: 6

username: halt,  userid: 7

username: mail,  userid: 8


        修饰符:

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

                如%3.1f

        -:左对齐  ,不加-为默认的右对齐

        +:显示数值的符号

[root@bucktan ~]# awk -F: '{printf "username: %-15s,  userid: %s\n",$1,$3}' /etc/passwd

username: root           ,  userid: 0

username: bin            ,  userid: 1

username: daemon         ,  userid: 2

##后面内容省略

   

7. 操作符

  ###(也是用在执行语句之中的,记得要用分号与print內建命令分开)

    算术操作符:

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

    -x:负值

    +x:转换为数值

    字符串操作符:没有符号的操作符,字符串连接

    赋值操作符:=,+=,-=,*=,/=,%=,++,--

    比较操作符:>,<,>=,<=,!=,==

    模式匹配符:

         ~:是否匹配

        !~:是否不匹配

    逻辑操作符:&&,||,!

    函数调用:function_name()  ,  

       若要传递参数使用:function_name(argu1,argu2,。。)

    条件表达式:selector?if-true-expression:if-false-expression

          selector为条件

          if-true-expression:条件为真的表达式

          if-false-expression:条件为假的表达式


eg:

[root@bucktan ~]# awk -F: '{$3>=1000?usertype="common user":usertype="sysuser or root";printf "%10s:%-s\n",$1,usertype}' /etc/passwd

      root:sysuser or root

       bin:sysuser or root

    daemon:sysuser or root

       adm:sysuser or root

        lp:sysuser or root

      sync:sysuser or root



     语法: gawk  [options ] ‘program’ file ...

         program:PATTERN{ACTION STATEMENTS}


8. PATTERN

    (1)empty:空模式,处理文本每一行

    (2):/regular expression/:仅处理能够被此模式匹配到的行

eg:

[root@bucktan ~]# awk '/^UUID\>/{print}' /etc/fstab

UUID=375e2006-28ec-4d8b-bc90-399b7c0f42f3 /boot                   ext4    defaults        1 2

      

    (3):relational expression:关系表达式,结果有“真”有”假“,结果为”真“才会被处理;

            "真":表示结果为非0值,或者为非空字符串

eg:

[root@bucktan ~]# awk -F: '$3>=1000{print $3}' /etc/passwd

65534

2000

    (4):line ranges 行范围

             startline,endline:/pat1/,/pat2

             注:支持直接给出数字

eg:

[root@bucktan ~]# awk -F: '/^root\>/,/^adm\>/{print $1,$3}' /etc/passwd

root 0

bin 1

daemon 2

adm 3


    (5):BEGIN/END

         BEGIN{}:仅在开始处理文件中的文本之前执行一次

         END{}:仅在文本处理完成之后执行一次


[root@bucktan ~]# awk -F: 'BEGIN{print "user      id\n================"}{print $1,$3}END{print "end\n-----------"}' /etc/passwd

user      id

================

root 0

bin 1

daemon 2

adm 3

[root@bucktan ~]# awk -F: 'BEGIN{print "user      id\n================"}{printf "%10-s %10-s\n",$1,$3}END{print "end\n-----------"}' /etc/passwd

user      id

================

root       0         

bin        1         

daemon     2         

adm        3     



     语法: gawk  [options ] ‘program’ file ...

         program:PATTERN{ACTION STATEMENTS}


9.常用的action语句(即写在{ACTION STATEMENTS}中的语句)


    a:Expressions

    b:cotrol statements:if ,while 等

    c:compound statements:组合语句

    d:input statements 输入语句

    e:output statements输出语句


  9.1 :控制语句

       if(condition) {statements}

       if(condition) {statements} else {statements}

       while(condition) {statements

       do {statements} while(condition)

       for(expr1;expr2;expr3) {statements}

       break

       continue

       delete array[index]

       delete array

       exit

       { statements }

10.细说action语句

  10.1  if -else

         语法: if(condition) statements else [statements]

eg:

[root@bucktan ~]# awk -F: '{if($3>=1000) print $1,$3}' /etc/passwd

nfsnobody 65534

apple 2000

[root@bucktan ~]# awk -F: '{if($3>=1000) {printf "common user: %s\n",$1} else { printf "root or sysuser:%s\n",$1}}' /etc/passwd

root or sysuser:root

root or sysuser:bin

root or sysuser:daemon

root or sysuser:adm

root or sysuser:lp

root or sysuser:sync


  10.2 while 循环

          语法:while(condition) {statements}

             条件为真进入循环为假退出循环

      使用场景:对一行内的多个字段逐一进行处理时使用;对数组中各元素逐一处理时使用

eg:对/etc/fstab文件中以UUID开头的行的每一个字段进行计算有多少个字符,并打印该字符段和字符数

[root@bucktan ~]# awk '/^UUID/{i=1;while(i<=NF) {print $i,length($i);i++}}' /etc/fstab

UUID=375e2006-28ec-4d8b-bc90-399b7c0f42f3 41

/boot 5

ext4 4

defaults 8

1 1

2 1


  10.3 do-while (先运行一次循环体,在判断条件)

        语法:do {statements} while(condition)

        意义:可以至少执行一次循环体

  10.4 for循环

        语法:for(expr1;expr2;expr3) {statements}

eg:

[root@bucktan ~]# awk '/^UUID/{for(i=1;i<=NF;i++){print $i,length($i)}}' /etc/fstab

UUID=375e2006-28ec-4d8b-bc90-399b7c0f42f3 41

/boot 5

ext4 4

defaults 8

1 1

2 1 

        特殊用法:

          能够遍历数组中的元素

           语法:for (var in array) {for-body}

  10.5 switch语句

        语法:switch(expression) {case VALUE1 or /REGEXP/:statement;case VALUE2 or /REGEXP/:statement;....;default:statement}

         注:其中之一分支匹配到,则执行此分支不执行其他分支了

  10.6 break和continue

      break [n]:退出n层循环

      continue:退出当前循环

  10.7 next 提前结束对本行的处理而直接进入下一行

eg:

[root@bucktan ~]# awk -F: '{if($3%2!=0) next ;print $1,$3}' /etc/passwd

root 0

daemon 2

lp 4

shutdown 6

     

  10.7 array

      关联数组:arry[index-expression]

        index-expression:

          (1):可使用任意字符,字符串要使用双引号

         (2):如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空串”

         若要判断数组中是否存在某元素,要使用“index in array”格式进行


11:函数

  11.1:内置函数

       数值处理:

           rand()::返回0和1之间一个随机数;


      字符串处理:

          length([s]):返回指定字符串的长度;

          sub(r,s,[t]):以r表示的模式来查找t所表示的字符中的匹配的内容,并将其第一次出现替换为s所表示的内容;

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


          split(s,a[,r]):以r为分隔符切割字符s,并将切割后的结果保存至a所表示的数组中;


~]# netstat -tan | awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++}END{for (i in count) {print i,count[i]}}'