• 文本处理工具awk


    文本处理工具awk
    awk:(Aho, Weinberger, Kernighan,)报告生成器,格式化文本输出 有多种版本:New awk(nawk),GNU awk( gawk) [toc] ## gawk:模式扫描和处理语言 ``` 1. 基本用法: awk [options] 'program' var=value file… awk [options] -f programfile var=value file… awk [options] 'BEGIN{action;… }pattern{action;… }END{action;… }' file ... awk 程序可由:BEGIN语句块、能够使用模式匹配的通用语句块、END语句块,共3部分组成 program 通常是被放在单引号中 2. 选项: -F “分隔符” 指明输入时用到的字段分隔符 -v var=value 变量赋值 ``` ## awk语言 ``` 1. 基本格式:awk [options] 'program' file… Program:pattern{action statements;..} pattern和action • pattern部分决定动作语句何时触发及触发事件 BEGIN,END • action statements对数据进行处理,放在{}内指明 print, printf 2. 分割符、域和记录 • awk执行时,由分隔符分隔的字段(域)标记$1,$2...$n称为域标识。$0 3. 为所有域,注意:此时和shell中变量$符含义不同 • 文件的每一行称为记录 • 省略action,则默认执行 print $0 的操作 ``` ⽣成需要的测试数据: [root@magedu ~]# head -10 /etc/passwd > awktest.txt ``` awk省略action,默认执⾏print $0 [root@centos7 ~]#head -10 /etc/passwd > /data/awktest.txt [root@centos7 ~]#cd [root@centos7 ~]#cd /data [root@centos7 data]#ls awktest.txt test vimrc.txt YYYY13.sh [root@centos7 data]#awk '{print}' awktest.txt 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 operator:x:11:0:operator:/root:/sbin/nologin ```

    awk工作原理

    1. 第一步:执行BEGIN{action;… }语句块中的语句
    2. 第二步:从文件或标准输入(stdin)读取一行,然后执行pattern{ action;… }语句块,
    它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。
    3. 第三步:当读至输入流末尾时,执行END{action;…}语句块
    4. BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,
    比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中
    5. END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的
    分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块
    6. pattern语句块中的通用命令是最重要的部分,也是可选的。如果没有提供
    pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每
    一行都会执行该语句块   
    
    【例1】BEGIN的使⽤:  
    [root@centos7 data]#awk '{print 2.5*3}' awktest.txt 
    7.5
    7.5
    7.5
    7.5
    7.5
    7.5
    7.5
    7.5
    7.5
    7.5
    [root@centos7 data]#awk 'BEGIN{print 2.5*3}' awktest.txt 
    7.5
    [root@centos7 data]#awk 'BEGIN{print 2.5*3}' 
    7.5
    
    

    print

    print格式:print item1, item2, ...

    要点:

    (1) 逗号分隔符
    (2) 输出item可以字符串,也可是数值;当前记录的字段、变量或awk的表达式
    (3) 如省略item,相当于print $0

     #示例:
    awk '{print "hello,awk"}'
    awk –F: '{print}' /etc/passwd
    awk –F: ‘{print “wang”}’ /etc/passwd
    awk –F: ‘{print $1}’ /etc/passwd
    awk –F: ‘{print $0}’ /etc/passwd
    awk –F: ‘{print $1”	”$3}’ /etc/passwd
    grep “^UUID”/etc/fstab | awk ‘{print $2,$4}’    
    
    【例1】指定:(冒号)为分隔符,打印每⾏记录的第⼀个字段即输出$1
    [root@centos7 data]#awk -F: '{print $1}' awktest.txt 
    root
    bin
    daemon
    adm
    lp
    sync
    shutdown
    halt
    mail
    operator    
    
    【例2】同理再把第三个字段输出,输出前添加三个连字符(---):  
    [root@centos7 data]#awk -F: '{print $1"---"$3}' awktest.txt 
    root---0
    bin---1
    daemon---2
    adm---3
    lp---4
    sync---5
    shutdown---6
    halt---7
    mail---8
    operator---11  
    
    【例3】取出磁盘使⽤率
    [root@centos7 data]#df
    Filesystem     1K-blocks     Used Available Use% Mounted on
    /dev/sda2      104806400  4543708 100262692   5% /
    devtmpfs          998216        0    998216   0% /dev
    tmpfs            1014056        0   1014056   0% /dev/shm
    tmpfs            1014056    10148   1003908   2% /run
    tmpfs            1014056        0   1014056   0% /sys/fs/cgroup
    /dev/sda3       52403200    35036  52368164   1% /data
    /dev/loop0      10491772 10491772         0 100% /mnt
    /dev/sda1        1038336   167036    871300  17% /boot
    tmpfs             202812        0    202812   0% /run/user/0  
      
    [root@centos7 data]#df |grep "^/dev"|awk -F" +|%" NR!=1'{print $5}'
    1
    100
    17
    
    [root@centos7 data]#df |awk -F" +|%" '{print $5}'
    Use
    5
    0
    0
    2
    0
    1
    100
    17
    0
    第一行去除写法。
    [root@centos7 data]#df |awk -F" +|%" NR!=1'{print $5}'
    5
    0
    0
    2
    0
    1
    100
    17
    0
    
    

    awk变量

    变量:内置和自定义变量

    FS:输入字段分隔符,默认为空白字符  
    awk -v FS=':' '{print $1,FS,$3}' /etc/passwd
    awk –F: '{print $1,$3,$7}' /etc/passwd  
    
    【例】 输⼊字段分隔符FS变量的使⽤  
    [15:14:02 root@centos6 ~]#awk -v FS=':' '{print$1,FS,$3}' /data/awktest
    root : 0
    bin : 1
    daemon : 2
    adm : 3
    lp : 4
    sync : 5
    shutdown : 6
    halt : 7
    mail : 8
    uucp : 10  
    
    OFS:输出字段分隔符,默认为空白字符
    awk -v FS=':' -v OFS=':' '{print $1,$3,$7}' /etc/passwd  
    
    【例】输⼊出字段分隔符OFS变量的使⽤   
    [15:14:17 root@centos6 ~]#awk -v FS=':' -v OFS='----' '{print $1,$3,$7}
    root----0----/bin/bash
    bin----1----/sbin/nologin
    daemon----2----/sbin/nologin
    adm----3----/sbin/nologin
    lp----4----/sbin/nologin
    sync----5----/bin/sync
    shutdown----6----/sbin/shutdown
    halt----7----/sbin/halt
    mail----8----/sbin/nologin
    uucp----10----/sbin/nologin
    
    RS:输入记录分隔符,指定输入时的换行符
    awk -v RS=' ' ‘{print }’ /etc/passwd  
    
    【例】输⼊记录分隔符RS变量的使⽤  
    [15:17:48 root@centos6 data]#awk -v RS=':' '{print}' /data/awktest.txt 
    root
    x
    0
    0
    root
    /root
    /bin/bash
    bin
    x
    1
    1
    bin
    /bin
    /sbin/nologin
    .
    .
    .
    .(省略)
    .
    .
    .
    .
    mail
    x
    8
    12
    mail
    /var/spool/mail
    /sbin/nologin
    uucp
    x
    10
    14
    uucp
    /var/spool/uucp
    /sbin/nologin
    
    ORS:输出记录分隔符,输出时用指定符号代替换行符
    awk -v RS=' ' -v ORS='###' '{print $0}' /etc/passwd  
    【例】输出记录分隔符ORS变量的使⽤(这里我试了一下有好多种用法我演示3种)  
    [15:19:10 root@centos6 data]#awk -v RS=':' -v ORS='-----' '{print}' /da
    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
    -----   (这里可以以冒号为分隔符用ORS替换掉)    
    
    [15:26:32 root@centos6 daawk  -v OR=' ' -v ORS='----' '{print}' /data/a
    root:x:0:0:root:/root:/bin/bash----bin:x:1:1:bin:/bin:/sbin/nologin-------lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin----sync:x:5:0:sync:/sbin:/b:/sbin/halt----mail:x:8:12:mail:/var/spool/mail:/sbin/nologin----uucp:x
    [15:27:40 root@centos6 data]#awk -v ORS='----' '{print}' /data/awktest.
    root:x:0:0:root:/root:/bin/bash----bin:x:1:1:bin:/bin:/sbin/nologin-------lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin----sync:x:5:0:sync:/sbin:/b:/sbin/halt----mail:x:8:12:mail:/var/spool/mail:/sbin/nologin----uucp:x 
    (这里OR加不加都一样的效果)
        
    [15:25:06 root@centos6 data]#awk  -v RS=':' -v ORS='----
    ' '{print}' /
    root----
    x----
    0----
    0----
    root----
    /root----
    /bin/bash
    bin----
    x----
    1----
    1----
    bin----
    /bin----
    /sbin/nologin
    daemon----
    x----
    2----
    2----
    daemon----
    /sbin----
    /sbin/nologin       (这就是回车换行的意思)
    
    NF:字段数量
    awk -F:'{print NF}' /etc/fstab 引用变量时,变量前不需加$
    awk -F:'{print $(NF-1)}' /etc/passwd   
    【例】字段数量NF变量的使⽤  
    [15:29:39 root@centos6 data]#awk -F: '{print NF}' awktest.txt 
    7
    7
    7
    7
    7
    7
    7
    7
    7
    7  
    [15:30:25 root@centos6 data]#awk -F: '{print $(NF-1)}' awktest.txt 
    /root
    /bin
    /sbin
    /var/adm
    /var/spool/lpd
    /sbin
    /sbin
    /sbin
    /var/spool/mail
    /var/spool/uucp
    
    
    NR:记录号
     awk '{print NR}' /etc/fstab ; awk END '{print NR}' /etc/fstab  
    
    【例】⾏号NR变量的使⽤  
    [15:32:33 root@centos6 data]#awk -F: '{print NR,$1}' awktest.txt 
    1 root
    2 bin
    3 daemon
    4 adm
    5 lp
    6 sync
    7 shutdown
    8 halt
    9 mail
    10 uucp
    
    FNR:各文件分别计数,记录号
    awk '{print FNR}' /etc/fstab /etc/inittab  
      
    【例】各⽂件分别的记录号FNR变量的使⽤  
    [15:32:39 root@centos6 data]#awk '{print FNR,$1}' /etc/fstab /data/awkt
    1 
    2 #
    3 #
    4 #
    5 #
    6 #
    7 #
    8 #
    1 root:x:0:0:root:/root:/bin/bash
    2 bin:x:1:1:bin:/bin:/sbin/nologin
    3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
    4 adm:x:3:4:adm:/var/adm:/sbin/nologin
    5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
    6 sync:x:5:0:sync:/sbin:/bin/sync
    7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
    8 halt:x:7:0:halt:/sbin:/sbin/halt
    9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    10 uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin  
    
    FILENAME:当前文件名
    awk '{print FILENAME}' /etc/fstab  
      
    【例】当前⽂件名FILENAME变量的使⽤  
    [15:34:03 root@centos6 data]#awk '{print FILENAME,FNR,$1}' /etc/fstab /
    /etc/fstab 1 
    /etc/fstab 2 #
    /etc/fstab 3 #
    /etc/fstab 4 #
    /etc/fstab 5 #
    /etc/fstab 6 #
    /etc/fstab 7 #
    /etc/fstab 8 #
    /data/awktest.txt 1 root:x:0:0:root:/root:/bin/bash
    /data/awktest.txt 2 bin:x:1:1:bin:/bin:/sbin/nologin
    /data/awktest.txt 3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
    /data/awktest.txt 4 adm:x:3:4:adm:/var/adm:/sbin/nologin
    /data/awktest.txt 5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
    /data/awktest.txt 6 sync:x:5:0:sync:/sbin:/bin/sync
    /data/awktest.txt 7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
    /data/awktest.txt 8 halt:x:7:0:halt:/sbin:/sbin/halt
    /data/awktest.txt 9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    /data/awktest.txt 10 uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin  
    
    ARGC:命令行参数的个数
    awk '{print ARGC}' /etc/fstab /etc/inittab
    awk 'BEGIN {print ARGC}' /etc/fstab /etc/inittab  
    
    【例】命令⾏参数的个数ARGC变量的使⽤ 
    [15:35:37 root@centos6 data]#awk 'BEGIN{print ARGC}' /etc/fstab /data/awktest.txt 
    3
    [15:47:06 root@centos6 data]#awk 'BEGIN{print ARGC}' /etc/fstab /data/awktest.txt /etc/shadow
    4  
    
    ARGV:数组,保存的是命令行所给定的各参数
    awk 'BEGIN {print ARGV[0]}' /etc/fstab /etc/inittab
    awk 'BEGIN {print ARGV[1]}' /etc/fstab /etc/inittab  
    
    【例】命令⾏给定的各参数的数组ARGV变量的使⽤  
    [16:42:16 root@centos6 data]#awk 'BEGIN{print ARGV[1]}' /etc/fstab /etc/inittab 
    /etc/fstab
    [16:42:22 root@centos6 data]#awk 'BEGIN{print ARGV[2]}' /etc/fstab /etc/inittab 
    /etc/inittab
    [16:42:41 root@centos6 data]#awk 'BEGIN{print ARGV[0]}' /etc/fstab /etc/inittab 
    awk
    

    自定义变量

    自定义变量(区分字符大小写)
    (1) -v var=value
    (2) 在program中直接定义
    示例:
    awk -v test='hello gawk' '{print test}' /etc/fstab
    awk -v test='hello gawk' 'BEGIN{print test}'
    awk 'BEGIN{test="hello,gawk";print test}'
    awk -F: '{sex=“male”;print $1,sex,age;age=18}' /etc/passwd
    cat awkscript
    {print script,$1,$2}
    awk -F: -f awkscript script="awk" /etc/passwd

    【例1】命令⾏给定的各参数的数组ARGV变量的使⽤  
    [17:03:28 root@centos6 data]#awk -F: -v name='username:' '{print name,$1}' awktest.txt 
    username: root
    username: bin
    username: daemon
    username: adm
    username: lp
    username: sync
    username: shutdown
    username: halt
    username: mail
    username: uucp 
    
    或变量定义在program⾥⾯为: 
    awk -F: '{name="username:";print name,$1}' awktest.txt    
    
    或在shell中定义了变量,在awk中⾃定义的变量调⽤shell中的变量:
    username="username"; awk -F: -v name=$username: '{print name,$1}' awktest.txt  
      
    【例2】把awk执⾏命令放⼊⼀个⽂件中,直接调⽤awk脚本⽂件  
    [17:07:41 root@centos6 data]#echo '{name="magedu";age=20;print name,$1,age}' > awkscript
    [17:11:19 root@centos6 data]#awk -F: -f awkscript awktest.txt 
    magedu root 20
    magedu bin 20
    magedu daemon 20
    magedu adm 20
    magedu lp 20
    magedu sync 20
    magedu shutdown 20
    magedu halt 20
    magedu mail 20
    magedu uucp 20
    

    printf命令

    格式化输出:printf “FORMAT”, item1, item2, ...
    (1) 必须指定FORMAT
    (2) 不会自动换行,需要显式给出换行控制符,
    (3) FORMAT中需要分别为后面每个item指定格式符
    格式符:与item一一对应
    %c:显示字符的ASCII码
    %d, %i:显示十进制整数
    %e, %E:显示科学计数法数值
    %f:显示为浮点数
    %g, %G:以科学计数法或浮点形式显示数值
    %s:显示字符串
    %u:无符号整数
    %%:显示%自身

    修饰符

    [.#] 第一个数字控制显示的宽度;第二个#表示小数点后精度,%3.1f

    • 左对齐(默认右对齐) %-15s
    • 显示数值的正负符号 %+d
    【例1】格式化输出,以冒号为分隔符,第⼀个字段宽度20个字符串,第⼆个字段宽度10个数⼦,⼀⾏输出2个字段,然后换⾏  
    [18:49:57 root@centos6 data]#awk -F: '{printf "%20s %10d
    ",$1,$3}' awktest.txt 
                   root          0
                    bin          1
                 daemon          2
                    adm          3
                     lp          4
                   sync          5
               shutdown          6
                   halt          7
                   mail          8
                   uucp         10
    注意:(默认输出是右对齐)  
    
    【例2】接上例,格式化输出为左对齐  
    [18:54:11 root@centos6 data]#awk -F: '{printf "%-20s %10d
    ",$1,$3}' awktest.txt 
    root                          0
    bin                           1
    daemon                        2
    adm                           3
    lp                            4
    sync                          5
    shutdown                      6
    halt                          7
    mail                          8
    uucp                         10
     
    【例3】以冒号为分隔符,每⾏输出”username:第⼀个字段“,然后换⾏  
    [18:55:46 root@centos6 data]#awk -F: '{printf "username:%s
    ",$1}' awktest.txt 
    username:root
    username:bin
    username:daemon
    username:adm
    username:lp
    username:sync
    username:shutdown
    username:halt
    username:mail
    username:uucp
     
    【例4】以冒号为分隔符,每⾏输出”username:第⼀个字段,左对齐,占20个宽度,UID:第三个字段“,然后换⾏  
    [18:58:26 root@centos6 data]#awk -F: '{printf "username:%-20s uid:%d
    ",$1,$3}' awktest.txt 
    username:root                 uid:0
    username:bin                  uid:1
    username:daemon               uid:2
    username:adm                  uid:3
    username:lp                   uid:4
    username:sync                 uid:5
    username:shutdown             uid:6
    username:halt                 uid:7
    username:mail                 uid:8
    username:uucp                 uid:10
    

    awk操作符

    1. 算术操作符:
      x+y:加法;
      x-y:减法;
      x*y:乘法;
      x/y:除法;
      x^y:幂运算;
      x%y:取模(余数)
      -x:转换为负数
      +x:将字符串转换为数值

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

    3. 赋值操作符:
      =:右边赋值给左边;
      +=:先加,再赋值;
      -=:先减,再赋值;
      *=:先乘,再赋值;
      /=:先除,再赋值;
      %=:先取余,再赋值;
      ^=:先幂运算,再赋值;
      ++:递增操作;
      --:递减操作。
      下面两语句有何不同
      • awk 'BEGIN{i=0;print ++i,i}'
      • awk 'BEGIN{i=0;print i++,i}'

    4. 比较操作符:
      ==:判断相等;
      !=:判断不等;
      >:判断大于;
      >=:判断大于等于;
      <:判断小于;
      <=:判断小于等于

    5. 模式匹配符:
      ~:左边是否和右边匹配包含;
      !~:是否不匹配。

    6. 逻辑操作符:
      逻辑与&&,
      逻辑或||,
      逻辑非!

    awk PATTERN:(awk的模式)
    PATTERN:根据pattern条件,过滤匹配的行,再做处理:

    1. 如果未指定:空模式,匹配每一行;
    2. /regular expression/:仅处理能够模式匹配到的行,需要用//扩起来;
    3. relational expression:关系表达式,结果为真,才会被处理;
      真:结果为非0值,非空字符串都是真;
      假:结果为空字符串或0值都是假。
    4. line ranges:行范围;
      startine,endline:/pat1/,/pat2/不支持直接给出数子格式。
    5. BEGIN/END模式
      BEGIN{}:仅在开始处理文件中的文本之前执行一次;
      END{}:仅在文本处理完成之后执行一次。

    awk的action:常⽤的action分类

    1. Expression:算术,比较表达式等;
    2. Control statuments:if,while等;
    3. conmpound statements:组合语句;
    4. input statements:
    5. output statements:print等。

    函数调⽤:
    funciton_name(argu1,argu2,...)

    1、awk使⽤算术操作符

        【例1】使⽤awk的算术操作符,计算2*3  
        [18:58:30 root@centos6 data]#awk 'BEGIN{print 2*3}'
    6  
    
        【例2】使⽤awk的算术操作符,取模5%2  
        [19:21:12 root@centos6 data]#awk 'BEGIN{print 5%2}'
    1  
    

    2、awk赋值操作符

        【例1】使⽤awk的+=赋值操作符  
        [19:21:25 root@centos6 data]#awk 'BEGIN{i=10;print i+=1}'
    11  
    
        【例2】使⽤awk的i++赋值操作符  
        [19:29:05 root@centos6 data]#awk 'BEGIN{i=10;print i++}'
    10  
    
        【例3】使⽤awk的++i赋值操作符  
        [19:32:58 root@centos6 data]#awk 'BEGIN{i=10;print ++i}'
    11
    [19:33:17 root@centos6 data]#awk 'BEGIN{i=10;print ++i;print i}'
    11
    11
    [19:33:27 root@centos6 data]#awk 'BEGIN{i=10;print ++i,i}'
    11 11  
    
        【例4】各种赋值操作符使用。(使用方法很多主要看你做什么。) 
    [19:33:30 root@centos6 data]#awk 'BEGIN{i=10;print --i,i}'
    9 9
    [19:34:18 root@centos6 data]#awk 'BEGIN{i/=10;print --i,i}'
    -1 -1
    [19:34:52 root@centos6 data]#awk 'BEGIN{i%=10;print --i,i}'
    -1 -1
    [19:35:15 root@centos6 data]#awk 'BEGIN{i^=10;print --i,i}'
    -1 -1
    [19:35:25 root@centos6 data]#awk 'BEGIN{i^=10;print ++i,i}'
    1 1
    [19:35:38 root@centos6 data]#awk 'BEGIN{i-=10;print ++i,i}'
    -9 -9
    [19:35:46 root@centos6 data]#awk 'BEGIN{i-=10;print --i,i}'
    -11 -11
    [19:36:35 root@centos6 data]#awk 'BEGIN{i=10;print i-=1}'
    9
    [19:36:38 root@centos6 data]#awk 'BEGIN{i=10;print i/=1}'
    10
    [19:38:37 root@centos6 data]#awk 'BEGIN{i=10;print i*=1}'
    10
    

    3、awk中的模式匹配符

        【例1】匹配包含root⾏的记录  
    [19:38:48 root@centos6 data]#awk -F: '$0 ~ /root/{print $0}' awktest.txt 
    root:x:0:0:root:/root:/bin/bash  
    
    [19:47:23 root@centos6 data]#awk -F: '$3==0' awktest.txt 
    root:x:0:0:root:/root:/bin/bash    (uid为0的不指定字段默认打印出来) 
    
    [19:48:43 root@centos6 data]#awk -F: '$0~ "^root"' awktest.txt 
    root:x:0:0:root:/root:/bin/bash    
      
        【例2】匹配不包含root⾏的记录
    [19:47:16 root@centos6 data]#awk -F: '$1 !~ /root/{print $0}' awktest.txt 
    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
      
        【例3】⽤正则表达式匹配包含root⾏的记录  
    [20:01:04 root@centos6 data]#awk -F: '$0 ~ /^root/{print $0}' awktest.txt 
    root:x:0:0:root:/root:/bin/bash    
    
        【例4】显⽰硬盘分区的使⽤率
    [20:08:20 root@centos6 data]#df -h |awk '$0 ~ /^/dev/sd/{print $1,$5}'
    /dev/sda2 4%
    /dev/sda1 4%
    /dev/sda3 1%
      
        【例5】从hostname.txt⽂件中,提取域名的第⼀部分  
    [20:14:09 root@centos6 data]#cat hostname.txt 
    magedu.com.com
    www.magedu.com
    mail.magedu.com
    [20:14:20 root@centos6 data]#awk -F'[.| ]' '{print $(NF-2)}' hostname.txt 
    magedu
    www
    mail
    

    4、awk的逻辑操作符

        【例1】显⽰第三字段⼤于等于0,且⼩于等于1000的⾏中的第1字段  
    [20:26:42 root@centos6 data]#awk -F: '$3>=0 && $3<=1000{print  $1}' /etc/passwd 
    root
    bin
    daemon
    adm
    lp
    sync
    shutdown
    halt
    .
    .
    .
    .
    haldaemon
    ntp
    apache
    saslauth
    postfix
    gdm
    pulse
    sshd
    tcpdump  
    
        【例2】显⽰第三字段等于0,或⼤于等于1000的⾏中的第1字段  
    [20:28:59 root@centos6 data]#awk -F: '$3==0 || $3>=1000{print $1}' /etc/passwd
    root
    nfsnobody   
    
        【例3】显⽰除了第三段等于0的⾏中的第1字段
    [20:29:57 root@centos6 data]#awk -F: '!($3==0){print $1}' /etc/passwd
    bin
    daemon
    adm
    lp
    sync
    shutdown
    halt
    mail
    uucp
    operator
    games
    gopher
    ftp
    nobody
    dbus
    usbmuxd
    rpc  
    
        【例4】awk实现打印奇数⾏和偶数⾏
    [20:31:47 root@centos6 data]#seq 10 |awk '!(i=!i)'
    2
    4
    6
    8
    10
    [20:33:41 root@centos6 data]#seq 10 |awk 'i=!i'
    1
    3
    5
    7
    9
    等同于sed命令:  
    [20:33:52 root@centos6 data]#seq 10 |sed -n '1~2p'
    1
    3
    5
    7
    9
    [20:34:59 root@centos6 data]#seq 10 |sed -n '2~2p'
    2
    4
    6
    8
    10  
    

    5、awk的PATTERN使⽤

        【例1】查找/etc/passwd⽂件中,以r开头的⾏,显⽰第1字段和第3字段  
    [20:35:04 root@centos6 data]#awk -F: '/^r/{print $1,$3}' /etc/passwd
    root 0
    rpc 32
    rtkit 499
    rpcuser 29  
    
        【例2】查找netstat -nt命令的结果中Foreign Address列的地址,并显⽰  
    [20:38:03 root@centos6 data]#netstat -nt |awk '/^tcp/{print $5}'|awk -F: '{print $1}'
    192.168.39.1  
    
        【例3】查找netstat -nt命令的结果中Foreign Address列的地址,统计每个地址链接的次数  
    [20:38:49 root@centos6 data]#netstat -nt |awk '/^tcp/{print $5}'|awk -F: '{print $1}'|sort|uniq -c
          1 192.168.39.1  
    
        【例4】匹配以f开头的⾏开始,到r开头的⾏结束之间的所有⾏  
    [20:40:44 root@centos6 data]#awk '/^f/,/^r/' /etc/passwd
    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
    usbmuxd:x:113:113:usbmuxd user:/:/sbin/nologin
    rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin  
       注意:如果没有⼀r开头的⾏,则会从匹配的以f开头的⾏开始,到最后都显⽰。   
    

    6、BRGIN/END模式

    【例】awk的BEGIN/END模式的使⽤  
    [20:52:49 root@centos6 data]#awk -F: 'BEGIN{print "user               id
    *********************"}{printf "%-10s|%10d
    ", $1,$3}END{print "*********************
     over"}' awktest.txt 
    user               id
    *********************
    root      |         0
    bin       |         1
    daemon    |         2
    adm       |         3
    lp        |         4
    sync      |         5
    shutdown  |         6
    halt      |         7
    mail      |         8
    uucp      |        10
    *********************
     over
    

    awk的条件判断

    掌握awk的条件判断。
    条件表达式:(三目表达式)
    selector?if-true-expression:if-false-expression

    控制语句:
    {statements;...}:组合语句;
    if(condition){statements;...}else {statements;...}
    if(condition1){statement1}else if(condition2){statement2}
    else{statement3}
    while(condition){statements;...}
    do {statements;...} while(condition)
    for(expr1;expr2;expr3) {statements;...}
    break
    continue
    delete array[index]
    delete array
    exit

    1、awk条件表达式的使⽤

     【例1】显⽰uid⼤于等于500,输出common user,⽤户名和uid,否则输出sysuser  
     [20:52:56 root@centos6 data]#awk -F: '{$3>=500?usertype="common user":usertype="sysuser";printf "%-15s %-20s %10d
    ",usertype,$1,$3}' /etc/passwd
    sysuser         root                          0
    sysuser         bin                           1
    sysuser         daemon                        2
    sysuser         adm                           3
    sysuser         lp                            4
    sysuser         sync                          5
    sysuser         shutdown                      6
    sysuser         halt                          7
    sysuser         mail                          8
    sysuser         uucp                         10
    sysuser         operator                     11
    sysuser         games                        12
    sysuser         gopher                       13
    sysuser         ftp                          14
    sysuser         nobody                       99
    sysuser         dbus                         81
    sysuser         usbmuxd                     113
    sysuser         rpc                          32
    sysuser         rtkit                       499
    sysuser         avahi-autoipd               170
    sysuser         vcsa                         69
    sysuser         abrt                        173
    sysuser         rpcuser                      29
    common user     nfsnobody                 65534
    sysuser         haldaemon                    68
    sysuser         ntp                          38
    sysuser         apache                       48
    sysuser         saslauth                    498
    sysuser         postfix                      89
    sysuser         gdm                          42
    sysuser         pulse                       497
    sysuser         sshd                         74
    sysuser         tcpdump                      72
    common user     yang                        500  
    
    【例2】查找netstat -nt命令的结果中Foreign Address列的地址,统计每个地址链接的次数,如果⼤于2次,显⽰ip  
    [21:07:46 root@centos6 data]#netstat -nt |awk '/^tcp/{print $5}'|awk -F: '{print $1}'|sort|uniq -c |awk '$1>1{print $2}'
    192.168.39.120  
    
    【例3】模拟并发访问http服务,查找ip连接次数超过200次的访问ip地址 模拟并发:  
    [root@magedu ~]# yum -y install httpd-tools
    [root@magedu ~]# ab -c 10 -n 200 http://172.18.120.26/    
    这里要记得打开httpd服务,然后确保你的seliunx和防火墙关闭。
    [21:22:58 root@centos6 data]#service httpd status
    httpd is stopped
    [21:23:56 root@centos6 data]#service httpd start
    Starting httpd: httpd: apr_sockaddr_info_get() failed for centos6.10yang.com
    httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for ServerName
                                                               [  OK  ]
    显⽰超过200次访问的ip:  (有两种方法)  
    
    [21:24:36 root@centos6 data]#awk '{print $1}' /var/log/httpd/access_log|sort|uniq -c
        207 192.168.39.6
    [21:24:39 root@centos6 data]#awk '{print $1}' /var/log/httpd/access_log|sort|uniq -c|awk '$1>200{print $2}'
    192.168.39.6  
    
    【例4】显⽰第10条到第20条记录的第1字段  
    [21:29:44 root@centos6 data]#awk -F: '(NR>=10 && NR<=20){print NR,$1}' /etc/passwd
    10 uucp
    11 operator
    12 games
    13 gopher
    14 ftp
    15 nobody
    16 dbus
    17 usbmuxd
    18 rpc
    19 rtkit
    20 avahi-autoipd  
    
    注意:显⽰从第10⾏到第20⾏内容,也可⽤sed命令实现:  
    [21:33:49 root@centos6 data]#sed -n '10,20p' /etc/passwd
    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
    usbmuxd:x:113:113:usbmuxd user:/:/sbin/nologin
    rpc:x:32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
    rtkit:x:499:499:RealtimeKit:/proc:/sbin/nologin
    avahi-autoipd:x:170:170:Avahi IPv4LL Stack:/var/lib/avahi-autoipd:/sbin/nologin
    

    2、awk组合语句

    【例】以冒号为分隔符,分别打印第1字段和第3字段
    [19:30:23 root@centos6 ~]#awk -F: '{print $1;print $3}' /data/awktest.txt 
    root
    0
    bin
    1
    daemon
    2
    adm
    3
    lp
    4
    sync
    5
    shutdown
    6
    halt
    7
    mail
    8
    uucp
    10
    [19:35:36 root@centos6 ~]#awk -F: '{print $1, $3}' /data/awktest.txt 
    root 0
    bin 1
    daemon 2
    adm 3
    lp 4
    sync 5
    shutdown 6
    halt 7
    mail 8
    uucp 10
        (组合语句和后面的写法还是不同的,组合会换行。)  
    

    3、if-else语句:对awk取得的整⾏或某字段做条件判断

    【例1】对第3字段判断⼤于等于500,则显⽰每⾏的用户名和UID。
    [19:39:21 root@centos6 ~]#awk -F: '{if($3>=500)print $1,$3}' /etc/passwd
    nfsnobody 65534
    yang 500
      
    【例2】查找最后⼀个字段是/bin/bash的⾏,打印第⼀个字段  
    [19:42:52 root@centos6 ~]#awk -F: '{if($NF=="/bin/bash")print $1}' /etc/passwd
    root
    yang
      
    【例3】查找以空格为分隔符,显⽰每⾏⼤于5个字段所在的⾏
    [19:46:12 root@centos6 ~]#awk '{if(NF>5) print $0}' /etc/fstab 
    # Created by anaconda on Fri Sep 20 20:04:25 2019
    # Accessible filesystems, by reference, are maintained under '/dev/disk'
    # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
    UUID=472ab1b1-b917-4e4f-8863-ff95e637dc61 /                       ext4    defaults        1 1
    UUID=0deb1cfb-a4d0-4d7a-916d-b5e6a1e9002a /boot                   ext4    defaults        1 2
    UUID=7c11fe6c-49e2-41ea-9464-c6be1e5187ec /data                   ext4    defaults        1 2
    UUID=c2af0f43-08f3-45b8-976c-9a10a38f441f swap                    swap    defaults        0 0
    tmpfs                   /dev/shm                tmpfs   defaults        0 0
    devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
    sysfs                   /sys                    sysfs   defaults        0 0
    proc                    /proc                   proc    defaults        0 0
      
    【例4】查找第3字段⼤于等500,则输出Common user:第1字段,否则输出root or Sysuer:第1字段  
    [19:54:17 root@centos6 ~]#awk -F: '{if($3>=500){printf "Common user:%s
    ",$1} else {printf"root or Sysuser:%s
    ",$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
    root or Sysuser:shutdown
    root or Sysuser:halt
    root or Sysuser:mail
    root or Sysuser:uucp
    root or Sysuser:operator
    root or Sysuser:games
    root or Sysuser:gopher
    root or Sysuser:ftp
    root or Sysuser:nobody
    root or Sysuser:dbus
    root or Sysuser:usbmuxd
    root or Sysuser:rpc
    root or Sysuser:rtkit
    root or Sysuser:avahi-autoipd
    root or Sysuser:vcsa
    root or Sysuser:abrt
    root or Sysuser:rpcuser
    Common user:nfsnobody
    root or Sysuser:haldaemon
    root or Sysuser:ntp
    root or Sysuser:apache
    root or Sysuser:saslauth
    root or Sysuser:postfix
    root or Sysuser:gdm
    root or Sysuser:pulse
    root or Sysuser:sshd
    root or Sysuser:tcpdump
    Common user:yang
    或:  
    [19:56:54 root@centos6 ~]#awk -F: '{if($3>=500)printf "Common user:%s
    ",$1;else printf "root or Sysuser:%s
    ",$1}' /etc/passwd  
    ......
    root or Sysuser:nobody
    root or Sysuser:dbus
    root or Sysuser:usbmuxd
    root or Sysuser:rpc
    root or Sysuser:rtkit
    root or Sysuser:avahi-autoipd
    root or Sysuser:vcsa
    root or Sysuser:abrt
    root or Sysuser:rpcuser
    Common user:nfsnobody
    root or Sysuser:haldaemon
    root or Sysuser:ntp
    ......  
      
    【例5】显⽰磁盘使⽤率⼤于等于4%的分区   
    [20:02:32 root@centos6 ~]#df -h |awk -F% '/^/dev/{print $1}' |awk '$NF>=4{print $1,$5}'
    /dev/sda2 4
    /dev/sda1 4
      
    【例6】判断awk⾃定义变量test的值,⼤于90则显⽰very good,⼤于60则显⽰good,其它值显⽰no pass  
    [20:02:48 root@centos6 ~]#awk 'BEGIN{test=100;if(test>90){print "very good"}else if(test>60){print "good"}else{print "no pass"}}'
    very good
    [20:05:53 root@centos6 ~]#awk 'BEGIN{test=89;if(test>90){print "very good"}else if(test>60){print "good"}else{print "no pass"}}'
    good
    [20:06:40 root@centos6 ~]#awk 'BEGIN{test=59;if(test>90){print "very good"}else if(test>60){print "good"}else{print "no pass"}}'
    no pass
    

    awk的循环

    掌握awk的循环。
    while(condition){statement;...}
    条件为真,进入循环,条件为假退出循环;
    使⽤场景:对⼀⾏内的多个字段逐⼀类似处理时使⽤;对数组中的各元素逐⼀处理时使⽤。

    do-while循环语法:do {statement;...}while(condition)无论真假,至少执行一次循环体。
    for循环语法:for(expr1;expr2;expr3){statement;...}

    常见用法:
    for(variable assignment;condition;iteration process
    {for-body}

    特殊用法:
    能够遍历数组中的元素:for(var in array){for-body}

    witch语句:
    语法:switch(expresssion){case VALUE1 or /REGEXP/:statement1;case VALUE2 or
    /REGEXP2/:statement2;...;default:statement}
    break、continue、next语句:
    break [n]:结束整个循环默认是最近的一次循环;
    continue [n]:跳过本轮循环,执行下一轮循环;
    next:提前结束对本行处理而直接进入下一行处理(awk自身循环)。

    1、awk中使⽤while循环

    【例1】统计第5⾏内容中每个单词分别有多少个字符  
    [20:37:30 root@centos6 ~]#awk '/ all/{i=1;while(i<=NF){print $i,length($i);++i}}' /etc/grub.conf 
    # 1
    all 3
    kernel 6
    and 3
    initrd 6
    paths 5
    are 3
    relative 8
    to 2
    /boot/, 7
    eg. 3
    [20:37:47 root@centos6 ~]#sed -n '5p' /etc/grub.conf 
    #          all kernel and initrd paths are relative to /boot/, eg.
      
    【例2】查找最⼤数和最⼩数  
    [20:45:10 root@centos6 data]#awk -F, '{min=$1;max=$1;i=1;while(i<=NF){if(max<$i)max=$i;if(min>$i)min=$i;i++};print "max:"max,"min:"min}' num.txt
    max:255 min:0
    或使用shell命令实现:
    [20:45:16 root@centos6 data]#for i in `tr ',' ' ' <num.txt`;do echo $i;done|sort -n|head
    0
    5
    6
    9
    16
    34
    111
    172
    192
    255
    [20:47:48 root@centos6 data]#for i in `tr ',' ' ' <num.txt`;do echo $i;done|sort -n|head -1
    0
    [20:47:52 root@centos6 data]#for i in `tr ',' ' ' <num.txt`;do echo $i;done|sort -n|tail -1
    255
      
    【例3】计算1+2+3+...+100的和  
    [20:58:18 root@centos6 data]#awk 'BEGIN{i=1;sum=0;while(i<=100){sum+=i;i++};print "sum="sum}'
    sum=5050 
    使用shell命令实现:
    [20:58:41 root@centos6 data]#sum=0;for i in {1..100};do let sum+=i; done;echo sum=$sum
    sum=5050
      
    【例4】awk中使⽤while循环计算10000内的总和  
    [21:00:28 root@centos6 data]#awk 'BEGIN{i=1;sum=0;while(i<=10000){sum+=i;i++};print "sum="sum}'
    sum=50005000
    

    2、awk中使⽤do-while循环

    【例】使⽤do-while计算100000内的和  
    [21:06:43 root@centos6 data]#awk 'BEGIN{total=0;i=0;do{total+=i;i++;}while(i<=100000);print total}'
    5000050000
    

    3、awk中使⽤for循环

    【例】计算100内整数的和
    [root@centos6 ~]# awk 'BEGIN{sum=0;for(i=1;i<=100;i++){sum+=i};print sum}'
    5050     
    

    4、性能⽐较

    【例】分别使⽤awk的while循环、shell的for循环等计算100000内的整数和,测试执⾏时间  
    [root@centos6 ~]# time (awk 'BEGIN{total=0;i=0;do{total+=i;i++;}while(i<=100000);print
    total}')
    5000050000
    real 0m0.013s
    user 0m0.012s
    sys 0m0.000s
    [root@centos6 ~]# time ( sum=0;for i in {1..100000};do let sum+=i;done;echo sum=$sum )
    sum=5000050000
    real 0m0.727s
    user 0m0.570s
    sys 0m0.157s
    [root@centos6 ~]# time ( seq -s "+" 100000|bc )
    5000050000
    real 0m0.107s
    user 0m0.102s
    sys 0m0.002s
    [root@centos6 ~]# time(for((i=0;i<=100000;i++));do let total+=i;done;echo $total)
    5000050000
    real 0m0.959s
    user 0m0.928s
    sys 0m0.030s  
    

    5、continue语句

    【例1】计算100内的奇数和
    [root@centos6 ~]# awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==0)continue;sum+=i}print sum}'
    2500 
    
    【例2】计算100内偶数和
    [root@centos6 ~]# awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2!=0)continue;sum+=i}print sum}'
    2550  
    

    6、break语句

    【例】计算100内的整数和,但遇到整数66就不计算了,退出执⾏
    [root@centos6 ~]# awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i==66)break;sum+=i}print sum}'
    2145  
    

    7、next语句

    【例】显⽰uid为偶数⾏的第1字段和第3字段  
    [root@centos6 ~]# awk -F: '{if($3%2!=0)next;print $1,$3}' awktest.txt
    root 0
    daemon 2
    lp 4
    shutdown 6
    mail 8
    uucp 10
    

    awk的数组

    1. 关联数组:array[index-expression]
    2. index-expression:
      可使用任意字符串;字符串要使用双引号括起来
      如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为空串
      若要判断数组中是否存在某元素,要使用index in array格式进行遍历
    3. 若要遍历数组中的每个元素,要使用for循环
    4. for(var in array){for-body}
    5. 注意:var会遍历array的每个索引

    1、awk中数组

    【例1】创建⼀个weekdays数组,显⽰索引为mon的数组的中的值
    [root@magedu ~]# awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print
    weekdays["mon"]}'
    Monday  
    
    【例2】使⽤awk中数组去重
    [root@magedu ~]# cat abc.txt
    a
    b
    c
    aa
    bb
    cc
    a
    b
    c
    [root@magedu ~]# awk '!arr[$0]++' abc.txt
    a
    b
    c
    aa
    bb
    cc  
    
    【例3】去重的思路演⽰
    [root@magedu ~]# awk '{!arr[$0]++;print $0,arr[$0]}' abc.txt
    a 1
    b 1
    c 1
    aa 1
    bb 1
    cc 1
    a 2
    b 2
    c 2  
    

    2、在awk中使⽤for循环遍历数组中的每个元素

    【例4】在awk中创建weekdays数组,并添加两个元素
    [root@magedu ~]# awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesay";for(i in
    weekdays) {print weekdays[i]}}'
    Monday
    Tuesay  
    
    【例5】统计netstat -tan命令结果中各个状态的数量
    ⽣成TIME-WAIT连接:
    [root@magedu ~]# ab -c 10 -n 200 http://172.16.103.78/
    统计各个tcp状态的个数:
    [root@magedu ~]# ss -tan|awk '!/State/{state[$1]++}END{for(i in state){print i,state[i]}}'
    ESTAB 1
    TIME-WAIT 207
    LISTEN 15  
    
    【例6】统计httpd的访问⽇志中每个ip访问的次数
    [root@magedu ~]# awk '{ip[$1]++}END{for(i in ip){print i,ip[i]}}' /var/log/httpd/access_log
    172.18.120.26 261
    172.18.116.232 3  
    
    【例7】统计连接本机的ip地址出现的次数
    [root@magedu ~]# ss -nt|awk -F '[ :]+' '!/State/{ip[$(NF-2)]++}END{for(i in ip){print
    i,ip[i]}}'
    172.16.101.234 1
    或统计访问次数前⼗的ip地址:
    [root@magedu ~]# ss -nt|awk -F '[ :]+' '!/State/{ip[$(NF-2)]++}END{for(i in ip){print
    i,ip[i]}}' | sort -nr -k2 | head  
    
    【例8】查找连接本机的次数⼤于20的ip地址,加⼊到防⽕墙禁⽌连接
    [root@magedu ~]# ss -nt | awk -F'[ :]+' '!/State/{ip[$(NF-2)]++}END{for(i in ip){print
    i,ip[i]}}' | while read line; do ip=`echo $line | awk '{if($2>20)print $1}'`;[ -z "$ip" ]
    || iptables -A INPUT -s $ip -j REJECT; done
    或⽤cut简单简单实现:
    [root@magedu ~]# ss -nt | awk -F'[ :]' '!/State/{ip[$(NF-2)]++}END{for(i in ip){print
    i,ip[i]}}' |while read line; do num=`echo $line | cut -d" " -f2`; ip=`echo $line | cut -d"
    " -f1`;[ $num -gt 3 ] && iptables -A INPUT -s $ip -j REJECT; done  
    
    【例9】有⼀个score.txt的⽂件,其内容是学⽣姓名、性别和分数,要求男⽣和⼥⽣的平均分
    [root@magedu ~]# cat socre.txt
    name sex score
    mage m 100
    wang m 90
    li f 99
    zhao f 95
    [root@magedu ~]# awk '!/name/{if($2=="m"){m++;msum+=$3};if($2=="f"){f++;fsum+=$3}}END{print
    "mavg="msum/m,"favg="fsum/f}' socre.txt
    mavg=95 favg=97
    或:
    [root@magedu ~]# awk '!/name/{num[$2]++;sum[$2]+=$3}END{for(i in num){print i "
    avg="sum[i]/num[i]}}' socre.txt
    m avg=95
    f avg=97  
    

    awk的函数

    1. 数值处理:
      rand():返回0和1之间的一个随机数,搭配srand()使用
    2. 字符串处理:
      length([s]):返回指定s字符串的长度
      sub(r,s[t]):对t字符串进行搜索r表示的模式匹配的内容,并将第一个匹配的内容替换为s
      gsub(r,s,[t]):对t字符串进行搜索r表示的模式匹配的内容,并全部替换为s所表示的内容
      split(s,array,[r]):以r为分隔符,切割字符串s,并将切割后的结果保存至array所表示的数组中,第一个索
      引值为1,第二个索引值为2,...
    3. ⾃定义函数:
      格式:
      function name (parameter1, parameter2, ...){
      statemenets
      return expression
      }

    1、rand()函数:⽣成随机数

    【例1】⽣成⼀个0到1之间的随机数
    [root@magedu ~]# awk 'BEGIN{print rand()}'
    0.237788
    [root@magedu ~]# awk 'BEGIN{print rand()}'
    0.237788
    [root@magedu ~]# awk 'BEGIN{print rand()}'
    0.237788
    [root@magedu ~]# awk 'BEGIN{srand(); print rand()}'
    0.792207
    [root@magedu ~]# awk 'BEGIN{srand(); print rand()}'
    0.046763
    [root@magedu ~]# awk 'BEGIN{srand(); print rand()}'
    0.046763
    或使⽤shell中⽣成随机数的⽅法:
    [root@magedu ~]# echo $RANDOM
    8149
    [root@magedu ~]# echo $RANDOM
    29261
    [root@magedu ~]# echo $RANDOM
    10121  
    
    【例2】使⽤awk的循环,⽣成10个0-1之间的随机数
    [root@magedu ~]# awk 'BEGIN{srand();for(i=0;i<10;i++)print rand()}'
    0.90757
    0.89926
    0.390811
    0.546444
    0.441346
    0.366411
    0.17337
    0.301543
    0.51216
    0.883284  
    
    【例3】使⽤awk的循环,利⽤int函数⽣成10个整数的随机数
    [root@magedu ~]# awk 'BEGIN{srand();for(i=0;i<10;i++)print int(rand()*100)}'
    1
    68
    10
    71
    94
    19
    77
    23
    18
    83  
    

    2、length()函数:统计字符长度

    【例4】计算“这是abc”的字符长度
    [root@magedu ~]# awk 'BEGIN{print length("这是abc")}'
    5  
    

    3、sub()函数:替换第⼀次匹配的字符

    【例5】把第⼀个冒号替换成连字符(-)
    [root@magedu ~]# echo "2018:08:17 15:47:50" |awk 'sub(/:/,"-",$1)'
    2018-08:17 15:47:50
    

    4、gsub()函数:全部替换

    【例6】把所有冒号替换成连字符(-)
    [root@magedu ~]# echo "2018:08:17 15:47:50" |awk 'gsub(/:/,"-",$0)'
    2018-08-17 15-47-50
    5、split()函数:指定分隔符,分隔字符串
    【例7】以冒号为分隔符,分别显⽰每个字段
    [root@magedu ~]# echo "2018:08:17 15:47:50" |awk '{split($0,array,":");print array[1]}'
    2018
    [root@magedu ~]# echo "2018:08:17 15:47:50" |awk '{split($0,array,":");print array[2]}'
    08
    [root@magedu ~]# echo "2018:08:17 15:47:50" |awk '{split($0,array,":");print array[3]}'
    17 15
    [root@magedu ~]# echo "2018:08:17 15:47:50" |awk '{split($0,array,":");print array[4]}'
    47
    [root@magedu ~]# echo "2018:08:17 15:47:50" |awk '{split($0,array,":");print array[5]}'
    50
    【例8】统计连接本机为建⽴状态的ip地址的数量
    [root@magedu ~]# netstat -tn|awk '/^tcp>/{split($5,ip,":");count[ip[1]]++}END{for(i in
    count){print i,count[i]}}'
    172.16.101.234 1   
    

    6、⾃定义函数

    【例9】获得两参数的最⼤值,⾃定义函数,在函数内部参数固定
    [root@magedu ~]# cat awk.fn
    function max(v1,v2){
    v1>v2?var=v1:var=v2
    return var
    }
    BEGIN{a=3;b=2;print max(a,b)}
    [root@magedu ~]# awk -f awk.fn
    3
    【例10】获得两参数的最⼤值,根据上例,把参数改为可变动的
    [root@magedu ~]# cat awk.fn
    function max(v1,v2){
    v1>v2?var=v1:var=v2
    return var
    }
    BEGIN{print max(a,b)}
    [root@magedu ~]# awk -v a=10 -v b=30 -f awk.fn
    30
    

    awk调⽤系统命令和其他功能

    1. system命令;
      空格是awk中的字符串连接符,如果system中需要使用awk中的变量可以使用空格分隔,或者说除了awk的变量外其
      他一律用""引用起来。
    2. awk的其他功能:
      将awk程序写成脚本,直接调用或执行
    3. 向awk脚本传递参数
      格式:awkfile var1=value1 var2=value2 ... Inputfile
    • 注意:在BEGIN过程中不可使⽤,直到⾸⾏输⼊完成以后,变量才可⽤;可通过-v参数,让awk在执⾏BEGIN之前得到变
      量的值;命令⾏中每⼀个指定的变量都需要⼀个-v参数。

    1、使⽤system()函数调⽤linux命令

    【例1】在awk中调⽤linux系统的hostname命令
    [root@magedu ~]# hostname
    magedu
    [root@magedu ~]# awk 'BEGIN{system("hostname")}'
    magedu
    【例2】在awk中使⽤linux中echo命令显⽰awk中的变量
    [root@magedu ~]# awk 'BEGIN{score=100;system("echo you score is "score)}'
    you score is 100
    【例3】在awk中使⽤iptables命令拒绝来源地址为1.1.1.1的访问
    [root@magedu ~]# awk 'BEGIN{ip="1.1.1.1";system("iptables -A INPUT -s " ip " -j REJECT")}'  
    

    2、awk脚本

    【例4】编写awk脚本,显⽰/etc/passwd中,uid⼤于500的⽤户和uid
    [root@magedu ~]# cat f1.awk
    #!/bin/awk -f
    {if($3>=500)print $1,$3}
    [root@magedu ~]# chmod +x f1.awk
    [root@magedu ~]# ./f1.awk -F: /etc/passwd
    nfsnobody 65534
    llj 500
    li 501
    zhang 502
    python 503  
    

    5、给awk脚本传递参数

    【例5】显⽰/etc/passwd⽂件中,uid在10-20之间的⽤户名和uid
    [root@magedu ~]# cat f2.awk
    #!/bin/awk -f
    {if($3>=min && $3<=max)print $1,$3}
    [root@magedu ~]# chmod +x f2.awk
    [root@magedu ~]# ./f2.awk -F: min=10 max=20 /etc/passwd
    uucp 10
    operator 11
    games 12
    gopher 13
    ftp 14
    或使⽤-v参数指定:
    [root@magedu ~]# ./f2.awk -F: -v min=10 -v max=20 /etc/passwd  
    
  • 相关阅读:
    python自动华 (十七)
    vue 链接
    hexo博客相关
    nodejs 安装 cnpm 命令
    centos7 node express项目 将http接口升级为https接口的解决方法
    centos7 showdoc 手动安装部署
    centos7 showdoc 安装部署
    npm install -d
    AngularJs出现错误Error: [ng:areq]
    AngularJs1使用中出现错误 Error: [ng:areq]
  • 原文地址:https://www.cnblogs.com/www233ii/p/11808999.html
Copyright © 2020-2023  润新知