zoukankan      html  css  js  c++  java
  • awk高级

    awk高级

    1. 工作流程

    我们要注意的一点就是awk是一行一行处理的,并不是一下子就把一整列给取出来了。

    打印列:

    [root@dy1 ~]# cat test.txt
    00 11 22
    33 44 55
    66 77 88
    
    //$0代表一整行
    [root@dy1 ~]# awk '{print $0}' test.txt
    00 11 22
    33 44 55
    66 77 88
    
    //NR的意思是行号
    [root@dy1 ~]# awk '{print NR,$0}' test.txt
    1 00 11 22
    2 33 44 55
    3 66 77 88
    
    //打印第一列和第三列
    [root@dy1 ~]# awk '{print $1,$3}' test.txt
    00 22
    33 55
    66 88
    
    //打印每一行有多少列
    [root@dy1 ~]# awk '{print NF}' test.txt
    3
    3
    3
    
    //打印最后一列
    [root@dy1 ~]# awk '{print $NF}' test.txt
    22
    55
    88
    
    //打印最后一列的数值减去1
    [root@dy1 ~]# awk '{print $NF-1}' test.txt
    21
    54
    87
    
    //打印倒数第二列
    [root@dy1 ~]# awk '{print $(NF-1)}' test.txt
    11
    44
    77
    
    [root@dy1 ~]# cat test.txt
    00:11 22
    33:44 55
    66:77 88
    
    //以:分隔,打印第二列
    [root@dy1 ~]# awk -F":" '{print $2}' test.txt
    11 22
    44 55
    77 88
    
    //以空格分隔,打印第二列
    [root@dy1 ~]# awk -F" " '{print $2}' test.txt
    22
    55
    88
    
    //以空格或者以冒号为分隔符打印
    [root@dy1 ~]# awk -F"[ :]" '{print $1}' test.txt
    00
    33
    66
    

    分隔符:

    //打印不规则的文本
    [root@dy1 ~]# cat test.txt
    00::11  22
    33::44     55
    66::77           88
    
    //分隔符可以有多个,而且可以连接出现多次
    [root@dy1 ~]# awk -F"[ :]+" '{print $1}' test.txt
    00
    33
    66
    [root@dy1 ~]# awk -F"[ :]+" '{print $NF}' test.txt
    22
    55
    88
    
    //FS相当于-F 指定什么为分隔符,使用-F实际就是修改FS
    [root@dy1 ~]# cat test.txt
    00::11  22
    33::44     55
    66::77           88
    [root@dy1 ~]# awk 'BEGIN {FS="[ :]+"} {print $NF}' test.txt
    22
    55
    88
    
    [root@dy1 ~]# awk 'BEGIN {FS="[ :]+"} {print $1,$2}' test.txt
    00 11
    33 44
    66 77
    
    //默认打印时分隔符是以空格,可以通过OFS指定打印时的分隔符
    [root@dy1 ~]# awk 'BEGIN {FS="[ :]+";OFS="@@"} {print $1,$2}' test.txt
    00@@11
    33@@44
    66@@77
    
    //小练习,分别用三剑客取出IP地址
    [root@dy1 ~]# ip addr show eth0 | awk 'NR==3{print $2}' | sed -r 's@(^.*)/24@1@'
    192.168.80.146
    [root@dy1 ~]# ip addr show eth0 | awk 'NR==3{print $2}' | egrep -o '^.*/' | tr -d /
    192.168.80.146
    [root@dy1 ~]# ip addr show eth0 | awk 'NR==3{print $2}' | awk -F"/" '{print $1}'
    192.168.80.146
    

    NR与FNR

    [root@dy1 ~]# cat test.txt 
    00::11  22
    33::44     55
    66::77           88
    [root@dy1 ~]# cat /etc/issue
    S
    Kernel 
     on an m
    
    //用NR如果对两个文件操作的话,行号会延续
    [root@dy1 ~]# awk 'BEGIN {FS="[ :]+";OFS="@@"} {print NR":"$1,$2}' test.txt /etc/issue
    1:00@@11
    2:33@@44
    3:66@@77
    4:S@@
    5:Kernel@@
    6:@@
    
    ////用FNR如果对两个文件操作的话,行号不会延续
    [root@dy1 ~]# awk 'BEGIN {FS="[ :]+";OFS="@@"} {print FNR":"$1,$2}' test.txt /etc/issue
    1:00@@11
    2:33@@44
    3:66@@77
    1:S@@
    2:Kernel@@
    3:@@
    

    打印行

    [root@dy1 ~]# cat test.txt 
    00::11  22
    33::44     55
    66::77           88
    
    //打印第二行
    [root@dy1 ~]# awk 'NR==2{print $0}' test.txt
    33::44     55
    [root@dy1 ~]# awk 'NR==2{print $1}' test.txt
    33::44
    [root@dy1 ~]# awk -F"[: ]+" 'NR==2{print $1}' test.txt
    33
    
    //打印大于第1号,小于第3行的行的第一列,其实也就是第二行的第一列。
    [root@dy1 ~]# awk -F"[: ]+" 'NR>1&&NR<3{print $1}' test.txt
    33
    
    //练习,打印用户的name和uid
    [root@dy1 ~]# awk -F: '{print "name:" $1 "	 uid:" $3}' /etc/passwd | head -5
    name:root	 uid:0
    name:bin	 uid:1
    name:daemon	 uid:2
    name:adm	 uid:3
    name:lp	 uid:4
    
    //通过print不美观,通过printf会美观一些
    [root@dy1 ~]# awk -F: '{printf "%-15s %-10s %-15s
    ",$1,$2,$3}' /etc/passwd | head -5
    root            x          0              
    bin             x          1              
    daemon          x          2              
    adm             x          3              
    lp              x          4         
    awk -F: '{printf "%-15s %-10s %-15s
    ","name:"$1,"this is:"$2,"uid:"$3}' /etc/passwd | head -5
    name:root       this is:x  uid:0          
    name:bin        this is:x  uid:1          
    name:daemon     this is:x  uid:2          
    name:adm        this is:x  uid:3          
    name:lp         this is:x  uid:4          
    
    • %s 字符类型
    • %d数值类型
    • 占15个字符,-表示左对齐,尾部是右对齐
    • printf 默认不会自动换行,需要加

    2. GEGIN&END

    [root@dy1 ~]# awk 'BEGIN {print "START"} {print "00"} END {print "END"}' /etc/hosts
    START
    00
    00
    END
    

    仔细体会上面的例子,为什么00会显示两次呢?是因为/etc/hosts的文件有两行,文件有几行,这里面的00就会打印几次,主要还是因为awk的工作原理使然,其工作原理就是取一行处理一行,文件当中一共有两行内容,这里面的00就会打印两次。

    那么BEGIN和END里面的内容只会打印一次呢?是因为BEGIN和END并不会参加到处理动作里面去,所以只打印一次,处理前打印一次,处理后打印一次。

    image-20200422084137330

    3. 模式动作

    正则表达式:

    #匹配记录(整行)
    [root@dy1 ~]# awk '/^root/' /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    [root@dy1 ~]# awk '$0 ~ /^root/' /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    

    匹配字段,匹配操作符

    [root@dy1 ~]# awk '$1~/^root/' /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    [root@dy1 ~]# awk '$1 !~ /bash$/' /etc/passwd
    bin:x:1:1:bin:/bin:/sbin/nologin
    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    

    比较表达式:

    [root@dy1 ~]# awk -F: '$3==0' /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    
    [root@dy1 ~]# awk -F: '$3<10' /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    bin:x:1:1:bin:/bin:/sbin/nologin
    
    [root@dy1 ~]# awk -F: '$7 == "/bin/bash"' /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    zhanghe:x:1000:1000::/home/zhanghe:/bin/bash
    
    //磁盘使用率大于多少则打印可用的值
    [root@dy1 ~]# df | awk '//$/'| awk '$3>100000 {print $4}' 
    44781576
    

    条件表达式:

    [root@dy1 ~]# awk -F: '$3>300 {print $0}' /etc/passwd
    polkitd:x:999:998:User for polkitd:/:/sbin/nologin
    nginx:x:998:996:nginx user:/var/cache/nginx:/sbin/nologin
    nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
    zhanghe:x:1000:1000::/home/zhanghe:/bin/bash
    
    [root@dy1 ~]# awk -F: '{if($3>300) print $0}' /etc/passwd
    polkitd:x:999:998:User for polkitd:/:/sbin/nologin
    nginx:x:998:996:nginx user:/var/cache/nginx:/sbin/nologin
    nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
    zhanghe:x:1000:1000::/home/zhanghe:/bin/bash
    
    [root@dy1 ~]# awk -F: '{if($3>5555) {print $3} else {print $1}}' /etc/passwd | head -5
    root
    bin
    daemon
    adm
    lp
    

    运算:

    [root@dy1 ~]# awk -F: '$3 * 10 > 50000' /etc/passwd
    nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
    

    4. if

    [root@dy1 ~]# df
    Filesystem              1K-blocks    Used Available Use% Mounted on
    /dev/mapper/centos-root  47023684 2242952  44780732   5% /
    devtmpfs                  1001880       0   1001880   0% /dev
    tmpfs                     1014044       0   1014044   0% /dev/shm
    tmpfs                     1014044    9776   1004268   1% /run
    tmpfs                     1014044       0   1014044   0% /sys/fs/cgroup
    /dev/sda1                 1038336  135368    902968  14% /boot
    tmpfs                      202812       0    202812   0% /run/user/0
    
    //当用量超过9000时,就打印可用的空间
    [root@dy1 ~]# df | awk '//run/{if ($3>9000) print "可用空间还有:"$4}'
    可用空间还有:1004268
    

    上述这个例子其实十分简单,取出有/run的行,如果第三列大于9000,就打印第四列。

  • 相关阅读:
    构造方法,析构函数
    Redis Sentinel实现的机制与原理详解
    关于PageRank的总结
    再次建立wordpress
    图的研究杂记
    并行的论文
    还是bib问题
    如何解决bib的一些问题
    忙中记录
    近期一些学术相关记录
  • 原文地址:https://www.cnblogs.com/yizhangheka/p/12762824.html
Copyright © 2011-2022 走看看