• Shell基础(六):使用awk提取文本、awk处理条件、awk综合脚本应用、awk流程控制、awk扩展应用


    一、使用awk提取文本

    目标:

    本案例要求使用awk工具完成下列过滤任务:

        1> 练习awk工具的基本用法
        2> 提取本机的IP地址、根分区使用率
        3> 格式化输出/etc/passwd文件中的用户名、UID、宿主目录信息

    格式化输出passwd文件内容时,要求第一行为列表标题,最后一行提示一共已处理文本的总行数,如下图所示。

                                    

    步骤:

    步骤一:awk文本过滤的基本用法

    1)基本操作方法

    格式:awk [选项] '[条件]{编辑指令}' 文件

    其中,print 是最常用的编辑指令;若有多条编辑指令,可用分号分隔

    处理文本时,若未指定分隔符,则默认将空格、制表符等作为分隔符

    直接过滤文件内容:

        [root@svr5 ~]# awk '{print $1,$2}' /etc/rc.local      //输出文件的第1、2列
        #!/bin/sh
        #
        # This
        # You
        # want
        touch /var/lock/subsys/local

    结合管道过滤命令输出:

        [root@svr5 ~]# uname -a                              //正常的完整输出
        Linux svr5.tarena.com 2.6.18-348.el5 #1 SMP Wed Nov 28 21:22:00 EST 2012 x86_64 x86_64 x86_64 GNU/Linux
        [root@svr5 ~]# uname -a | awk '{print $1,$3,$12}'      //输出第1、3、12字段
        Linux 2.6.18-348.el5 x86_64

    2)选项 -F 可指定分隔符

    截取/etc/passwd文件的前7行,用来创建一个测试文件,操作如下:

        [root@svr5 ~]# head -7 /etc/passwd > passwd.txt
        [root@svr5 ~]# cat passwd.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

    输出passwd.txt文件中以分号分隔的第1、7个字段,显示的不同字段之间以逗号隔开,操作如下:

        [root@svr5 ~]# awk -F: '{print $1","$7}' passwd.txt
        root,/bin/bash
        bin,/sbin/nologin
        daemon,/sbin/nologin
        adm,/sbin/nologin
        lp,/sbin/nologin
        sync,/bin/sync
        shutdown,/sbin/shutdown

    或者:

        [root@svr5 ~]# awk -F ":" '{print $1","$7}' passwd.txt
        root,/bin/bash
        bin,/sbin/nologin
        daemon,/sbin/nologin
        adm,/sbin/nologin
        lp,/sbin/nologin
        sync,/bin/sync
        shutdown,/sbin/shutdown

    awk还识别多种单个的字符,比如以“:”或“/”分隔,输出第1、10个字段:

        [root@svr5 ~]# awk -F [:/] '{print $1,$10}' passwd.txt
        root bash
        bin nologin
        daemon nologin
        adm sbin
        lp
        sync sync
        shutdown shutdown

    输出每次处理的行号,以及当前行以“:”分隔的字段个数:

        [root@svr5 ~]# awk -F: '{print NR,NF}' passwd.txt
        1 7
        2 7
        3 7
        4 7
        5 7
        6 7
        7 7

    3)awk处理的时机

    awk会逐行处理文本,支持在处理第一行之前做一些准备工作,以及在处理完最后一行之后做一些总结性质的工作。在命令格式上分别体现如下:

        行前处理,BEGIN{ }
        逐行处理,{ }
        行后处理,END{ }

    上述编辑指令段可以包含在一对单引号内,比如:

       awk  [选项]  ' BEGIN{编辑指令 } {编辑指令} END{编辑指令}'  文件

    只做预处理的时候,可以没有操作文件,比如:

        [root@svr5 ~]# awk 'BEGIN{A=1024;print A*2.56}'
        2621.44

    举个包括三个处理时机的例子——“统计系统中使用bash作为登录Shell的用户总个数:预处理时赋值变量x=0,然后逐行读入/etc/passwd 文件检查,如果发现登录Shell是/bin/bash则x增加1,全部处理完毕后,输出x的值即可。相关操作及结果如下:

        [root@svr5 ~]# awk 'BEGIN{x=0}/<bash$/{x++} END{print x}' /etc/passwd
        29

    当然,这个例子比较简单(效果与egrep -c '<bash$' /etc/passwd 相同),此处仅仅是用来说明awk三种处理时机的用法。在实际工作中,利用awk的这种处理流程可以完成许多更复杂的任务。

    步骤二:利用awk提取本机的IP地址、根分区使用率

    1)提取IP地址

    分步实现的思路及操作参考如下——

    通过ifconfig eth0查看网卡信息,其中包括IP地址:

        [root@svr5 ~]# ifconfig eth0
        eth0      Link encap:Ethernet  HWaddr 00:0C:29:82:09:E9
                  inet 192.168.4.4  Bcast:192.168.4.255  Mask:255.255.255.0
                  inet6 addr: fe80::20c:29ff:fe82:9e9/64 Scope:Link
                  UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
                  RX packets:358524 errors:0 dropped:0 overruns:0 frame:0
                  TX packets:230638 errors:0 dropped:0 overruns:0 carrier:0
                  collisions:0 txqueuelen:1000
                  RX bytes:44470760 (42.4 MiB)  TX bytes:64236279 (61.2 MiB)

    结合grep获得包含IP地址的那一行:

        [root@svr5 ~]# ifconfig eth0 | grep "inet"
                  inet addr:192.168.4.4  Bcast:192.168.4.255  Mask:255.255.255.0

    再结合awk过滤出第2列:

        [root@svr5 ~]# ifconfig eth0 | grep "inet" | awk '{print $2}'
        192.168.4.4

    2)提取根分区使用率

    分步实现的思路及操作参考如下——

    通过df命令查看根分区的使用情况,其中包括使用率:

        [root@svr5 ~]# df -hT /
        文件系统         类型     容量     已用     可用     已用%     挂载点
        /dev/sda2     ext3     19G         7.2G     11G         40%         /

    输出上述结果中最后一行的第6列:

        [root@svr5 ~]# df -hT / | tail -1 | awk '{print $6}'
        40%

    步骤三:格式化输出/etc/passwd文件

    1)任务需求及实现思路分析

    根据任务要求的结果,输出的内容包括三个部分:列表头、用户信息、列表尾。

    由于/etc/passwd文件中的用户记录是单一的以“:”分隔,而且恰好awk本身就已经支持“前、中、后”三段式处理,所以用awk处理是再合适不过了。通过awk的内置变量NR即可获得处理的记录行数,因此只要设置正确的输出即可。

    2)根据实现思路编写、验证awk过滤语句

    输出信息时,可以使用“ ”显示Tab制表位:

        [root@svr5 ~]# awk -F: 'BEGIN{print "User UID Home"}
        {print $1" "$3" "$6} END{print "Total "NR" lines."}' /etc/passwd
        User    UID     Home
        root    0       /root
        bin     1       /bin
        daemon  2       /sbin
        adm     3       /var/adm
        lp      4       /var/spool/lpd
        sync    5       /sbin
        .. ..
        iamkiller       1234    /opt/.private/iamkiller
        nsd001  0       /home/nsd001
        nsd002  1236    /home/nsd002
        nsd003  1237    /home/nsd003
        postfix 89      /var/spool/postfix
        Total 67 lines.

    二、awk处理条件

    目标:

    本案例要求使用awk工具完成下列过滤任务,注意awk处理条件的设置:

        1> 列出UID间于501~505的用户详细信息
        2> 输出/etc/hosts文件内以127或192开头的记录
        3> 列出100以内整数中7的倍数或是含7的数

    步骤:

    步骤一:认识awk处理条件的设置

    创建测试文件passwd.txt文件:

        [root@svr5 ~]# head -7 /etc/passwd > passwd.txt
        [root@svr5 ~]# cat passwd.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

    1)使用正则表达式设置条件

    输出其中以bash结尾的完整记录:

        [root@svr5 ~]# awk -F: '/bash$/{print}' passwd.txt
        root:x:0:0:root:/root:/bin/bash

    输出以a、b、c或d开头的用户名、宿主目录:

        [root@svr5 ~]# awk -F: '/^[a-d]/{print $1,$6}' passwd.txt
        bin /bin
        daemon /sbin
        adm /var/adm

    输出其中用户名以a开头、登录Shell以nologin结尾的用户名、登录Shell:

        [root@svr5 ~]# awk -F: '/^a|nologin$/{print $1,$7}' passwd.txt
        bin /sbin/nologin
        daemon /sbin/nologin
        adm /sbin/nologin
        lp /sbin/nologin

    输出其中宿主目录以bin结尾(对第6个字段做~匹配)的用户名、宿主目录信息:

        [root@svr5 ~]# awk -F: '$6~/bin$/{print $1,$6}' passwd.txt
        bin /bin
        daemon /sbin
        sync /sbin
        shutdown /sbin

    输出其中登录Shell不以nologin结尾(对第7个字段做!~反向匹配)的用户名、登录Shell信息:

        [root@svr5 ~]# awk -F: '$7!~/nologin$/{print $1,$7}' passwd.txt
        root /bin/bash
        sync /bin/sync
        shutdown /sbin/shutdown

    2)使用数值/字符串比较设置条件

    输出第3行(行号NR等于3)的用户记录:

        [root@svr5 ~]# awk -F: 'NR==3{print}' passwd.txt
        daemon:x:2:2:daemon:/sbin:/sbin/nologin

    输出奇数行(行号NR除以2余数为1)的用户记录:

        [root@svr5 ~]# awk -F: 'NR%2==1{print}' passwd.txt
        root:x:0:0:root:/root:/bin/bash
        daemon:x:2:2:daemon:/sbin:/sbin/nologin
        lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
        shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

    输出偶数行(行号NR除以2余数为0)的用户记录:

        [root@svr5 ~]# awk -F: 'NR%2==0{print}' passwd.txt
        bin:x:1:1:bin:/bin:/sbin/nologin
        adm:x:3:4:adm:/var/adm:/sbin/nologin
        sync:x:5:0:sync:/sbin:/bin/sync

    输出前3行文本:

        [root@svr5 ~]# awk -F: 'NR<=3{print}' passwd.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

    输出从第5行开始到文件末尾的所有行:

        [root@svr5 ~]# awk -F: 'NR>=5{print}' passwd.txt
        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

    输出用户名为“sync”的行:

        [root@svr5 ~]# awk -F: '$1=="sync"{print}' passwd.txt
        sync:x:5:0:sync:/sbin:/bin/sync

    输出当前用户的用户名、宿主目录、登录Shell信息:

        [root@svr5 ~]# awk -F: '$1==ENVIRON["USER"]{print $1,$6,$7}' passwd.txt
        root /root /bin/bash

    3)逻辑测试条件

    输出第3~5行文本:

        [root@svr5 ~]# awk -F: 'NR>=3&&NR<=5{print}' passwd.txt
        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

    严谨一点可以写成:

        [root@svr5 ~]# awk -F: '(NR>=3)&&(NR<=5){print}' passwd.txt
        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

    输出第3行和第5行文本:

        [root@svr5 ~]# awk -F: 'NR==3||NR==5{print}' passwd.txt
        daemon:x:2:2:daemon:/sbin:/sbin/nologin
        lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

    输出“登录Shell不以nologin结尾”或者“用户名以a或d开头”的文本:

        [root@svr5 ~]# awk -F: '$7!~/nologin$/||$1~/^[ad]/{print}' passwd.txt
        root:x:0:0:root:/root:/bin/bash
        daemon:x:2:2:daemon:/sbin:/sbin/nologin
        adm:x:3:4:adm:/var/adm:/sbin/nologin
        sync:x:5:0:sync:/sbin:/bin/sync
        shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

    输出UID小于3或者UID是偶数的用户记录:

        [root@svr5 ~]# awk -F: '$3<3||$3%2==0{print}' passwd.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
        lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
        shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

    4)数学运算

    以统计passwd.txt文件中以“:”分隔的总字段个数,需要每处理一行时将当前行的字段数(内置变量NF)计和,因此可在BEGIN时定义一个初始变量,过程称求和,最后在END时输出结果。

    相关操作及结果如下(共49个字段):

        [root@svr5 ~]# awk -F: 'BEGIN{x=0}
         {x+=NF} END{print "Total "x" fields."}' passwd.txt
        Total 49 fields.

    步骤二:完成任务要求的awk过滤操作

    1)列出UID间于501~505的用户详细信息:

        [root@svr5 ~]# awk -F: '$3>=501&&$3<=505{print}' /etc/passwd
        hunter:x:501:501::/home/hunter:/bin/bash
        vina:x:502:502::/home/vina:/bin/bash
        kdev:x:503:503::/home/kdev:/bin/bash
        zengye:x:504:504::/home/zengye:/bin/bash
        stu01:x:505:1201::/tech/nsdhome/stu01:/bin/bash

    2)输出/etc/hosts映射文件内以127或者192开头的记录:

        [root@svr5 ~]# awk -F: '/^127|^192/{print}' /etc/hosts
        127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
        192.168.4.5  svr5.tarena.com svr5

    3)列出100以内整数中7的倍数或是含7的数:

    此操作无处理文件,正常思路应该是用Shell循环来完成;因为要求用awk来实现,如果不用循环,则根据逐行处理的思路,应该提供一个100行的文本对象,然后将行号作为处理的整数,逐个判断并输出即可。

    利用seq命令可生成1-100的整数序列,比如:

        [root@svr5 ~]# seq 100
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        .. ..

    结合管道交给awk处理,可以简化实现步骤。针对本任务而言,行号与每行的实际文本值是一致的,那么根据NR或者$0行值进行判断都是可以的。输出100以内7的倍数或是包含7的数:

        [root@svr5 ~]# seq 100 | awk 'NR%7==0||NR~/7/{print}'
        7
        14
        17
        21
        27
        28
        35
        37
        42
        47
        .. ..

    或者:

        [root@svr5 ~]# seq 100 | awk '$0%7==0||$0~/7/{print}'
        7
        14
        17
        21
        27
        28
        35
        37
        42
        47
        .. ..

    三、awk综合脚本应用

    目标:

    本案例要求编写脚本getupwd-awk.sh,实现以下需求:

        1> 找到使用bash作登录Shell的本地用户
        2> 列出这些用户的shadow密码记录
        3> 按每行“用户名 --> 密码记录”保存到getupwd.log,如下图所示

                               

    步骤:

    步骤一:任务需求及思路分析

    编写getupwd-awk.sh脚本的任务要求如下:

    • 分析出使用bash作登录Shell的本地用户
    • 列出这些用户的shadow密码记录
    • 按每行“用户名 -- 密码记录”保存结果

    步骤二:根据实现思路编写脚本

    复制原getupwd.sh脚本,生成getupwd-awk.sh:

        [root@svr5 ~]# cat getupwd.sh                      //确认原脚本内容
        #/bin/bash
        > /tmp/getupwd.log                                     ## 创建空文件
        sed -n '/:/bin/bash$/w /tmp/urec.tmp' /etc/passwd      ## 提取符合条件的账号记录
        UNUM=$(egrep -c '.' /tmp/urec.tmp)                   ## 取得记录个数
        while [ ${i:=1} -le $UNUM ]                         ## 从第1行开始,遍历账号记录
        do
            UREC=$(sed -n "${i}p" /tmp/urec.tmp)              ## 取指定行数的记录
            NAME=${UREC%%:*}                                 ## 截取用户名(记录去尾)
            PREC=$(sed -n "/^$NAME:/p" /etc/shadow)          ## 查找与用户名对应的密码记录
            PASS=${PREC#*:}                                  ## 掐头
            PASS=${PASS%%:*}                                ## 去尾,只留下密码记录
            echo "$NAME --> $PASS" >> /tmp/getupwd.log         ## 保存结果
            let i++                                           ## 自增1,转下一次循环
        done
        /bin/rm -rf /tmp/urec.tmp                           ## 删除临时文件
        echo "用户分析完毕,请查阅文件 /tmp/getupwd.log"         ## 完成后提示
        [root@svr5 ~]# cp getupwd.sh getupwd-awk.sh          //复制为新脚本文件

    修改新脚本文件,内容参考如下:

        [root@svr5 ~]# vim getupwd-awk.sh
        #/bin/bash
        ## 创建空文件
        > /tmp/getupwd.log
        ## 提取用户名列表
        awk -F: '/:/bin/bash$/{print $1}' /etc/passwd > /tmp/users.tmp
        ## 通过for循环遍历用户名、查询密码记录,保存结果
        for NAME in $(cat /tmp/users.tmp)
        do
            grep "^$NAME:" /etc/shadow | awk -F: '{print $1" --> "$2 |
            "cat >> /tmp/getupwd.log"}' /etc/shadow
        done
        echo "用户分析完毕,请查阅文件 /tmp/getupwd.log" ## 完成后提示
        [root@svr5 ~]# chmod +x getupwd-awk.sh

    步骤三:验证、测试脚本

        [root@svr5 ~]# ./getupwd-awk.sh      
        用户分析完毕,请查阅文件 /tmp/getupwd.log
        [root@svr5 ~]# head -5 /tmp/getupwd.log
        root --> $6$IWgMYmRACwdbfwBo$dr8Yn983nswiJVw0dTMjzbDvSLeCd1GMYjbvsDiFEkL8jnXOLcocBQypOCr4C6BRxNowIxjh6U2qeFU0u1LST/
        zengye --> $6$Qb37LOdzRl5995PI$L0zTOgnhGz8ihWkW81J.5XhPp/l7x2./Me2ag0S8tRndCBL9nIjHIKkUKulHxJ6TXyHYmffbVgUT6pbSwf8O71
        clamav --> !!
        mysql --> !!
        abc --> !!
        .. ..

    四、awk流程控制

    目标:

    本案例要求了解awk的流程控制操作,可自行设置awk语句来有验证以下操作:

         1> if分支结构(双分支、多分支)
         2> while循环结构
         3> break、continue等其他控制语句

    步骤:

    步骤一:awk过滤中的if分支结构

    1)单分支

    统计/etc/passwd文件中UID小于或等于500的用户个数:

        [root@svr5 ~]# awk -F: 'BEGIN{i=0}{if($3<=500){i++}}END{print i}' /etc/passwd
        39

    统计/etc/passwd文件中UID大于500的用户个数:

        [root@svr5 ~]# awk -F: 'BEGIN{i=0}{if($3>500){i++}}END{print i}' /etc/passwd
        28

    统计/etc/passwd文件中登录Shell是“/bin/bash”的用户个数:

        [root@svr5 ~]# awk -F: 'BEGIN{i=0}{if($7~/bash$/){i++}}END{print i}'
         /etc/passwd
        29

    统计/etc/passwd文件中登录Shell不是“/bin/bash”的用户个数:

        [root@svr5 ~]# awk -F: 'BEGIN{i=0}{if($7!~/bash$/){i++}}END{print i}'
         /etc/passwd
        38

    2)双分支

    分别统计/etc/passwd文件中UID小于或等于500、UID大于500的用户个数:

        [root@svr5 ~]# awk -F: 'BEGIN{i=0;j=0}{if($3<=500){i++}else{j++}}END{print i,j}' /etc/passwd
        39 28

    分别统计/etc/passwd文件中登录Shell是“/bin/bash”、 登录Shell不是“/bin/bash”的用户个数:

        [root@svr5 ~]# awk -F: 'BEGIN{i=0;j=0}{if($7~/bash$/){i++}else{j++}}
        END{print i,j}' /etc/passwd
        29 38

    3)多分支

    分别统计/etc/passwd文件中登录Shell是“/bin/bash”、“/sbin/nologin”、其他的用户个数:

        [root@svr5 ~]# awk -F: 'BEGIN{i=0;j=0;k=0}{if($7~/bash$/){i++}
        else if($7~/nologin$/){j++}else{k++}}END{print i,j,k}' /etc/passwd
        29 33 5

    步骤二:awk过滤中的while循环结构

    1)while循环

    统计/etc/passwd文件内“root”出现的次数。

    —— 分析:以“:”或“/”做分隔,针对每一行的每一列进行比对,如果包含“root”,则次数加1。其中,逐行处理直接由awk完成,逐列处理交给while循环,通过i变量依次取$1、$2、……、$NF进行检查;变量j在预处理时赋值0,没匹配一个字段加1。

        [root@svr5 ~]# awk -F [:/]
        'BEGIN{j=0}
        {i=1}{while(i<=NF){if($i~/root/){j++};i++}}
        END{print j}'  /etc/passwd
        4

    此例仅为说明while循环的用法。

    实际应用时,上述操作可以简单处理,可通过命令替换将文件内容赋值给一个变量(变为一行文本),然后针对此变量值以目标字符串“root”作为分隔,获取总字段数-1即可得目标字符串的总数量:

        [root@svr5 ~]# echo $(cat /etc/passwd) | awk -F "root" '{print NF-1}'
        4

    五、awk扩展应用

    目标:

    本案例要求使用awk工具完成下列两个任务:

    •  分析Web日志的访问量排名,要求获得客户机的地址、访问次数,并且按照访问次数排名

    方案:

    1)awk统计Web访问排名

    在分析Web日志文件时,每条访问记录的第一列就是客户机的IP地址,其中会有很多重复的IP地址。因此只用awk提取出这一列是不够的,还需要统计重复记录的数量并且进行排序。

    通过awk提取信息时,利用IP地址作为数组下标,每遇到一个重复值就将此数组元素递增1,最终就获得了这个IP地址出现的次数。

    针对文本排序输出可以采用sort命令,相关的常见选项为-r、-n、-k。其中-n表示按数字顺序升序排列,而-r表示反序,-k可以指定按第几个字段来排序。

    步骤:

    步骤一:统计Web访问量排名

    分步测试、验证效果如下所述。

    1)提取IP地址及访问量

        [root@svr5 ~]# awk  '{ip[$1]++} END{for(i in ip) {print i,ip[i]}}' /var/log/httpd/access_log
        127.0.0.1 4
        192.168.4.5 17
        192.168.4.110 13
        .. ..

    2)对第1)步的结果根据访问量排名

        [root@svr5 ~]# awk  '{ip[$1]++} END{for(i in ip) {print i,ip[i]}}' /var/log/httpd/access_log | sort -nr -k 2
        192.168.4.5 17
        192.168.4.110 13
        127.0.0.1 4
        .. ..

    附加:

    awk数据过滤软件【统计功能】;类似grep  【过滤一整行】

    awk [选项] '条件{指令}'  文件
    条件可以没有【默认为所有】
    指令可以没有【打印整行】
    不能条件指令都没有
    awk默认使用空格或Tab键作为分割符

    print $0      #读一行就打印当前一整行
    print $1      #读一行就打印第一列
    print $2      #读一行就打印第二列
    ...
    print NR      #读一行就打印当前行的行号
    print NF      #读一行就打印当前行的列数
    # awk -F: '{print NR}' /etc/passwd   #读一行就打印一次当前的行号
    # awk -F: '{print NF}' /etc/passwd   #读一行就打印当前行所有的列数
    # awk -F: '{print $NF}' /etc/passwd   #读一行就打印当前行最后一列

    打印常量(字符串需要引号)
    awk '{print "dachui"}' /etc/passwd    //这个文件有多少行就打印多少行的dachui
    # awk -F: '{print "第"NR"行","有"NF"列"}' /etc/passwd   打印多少行有多少列
    # awk -F: '{print "第"NR"行","有"NF"列"}' /etc/passwd|head -34|tail -1  只打印第34行有几列

    awk 'BEGIN{} 条件{}  END{}' 文件         # 三个条件不一定要全有,有一个就可以
    所有的指令都需要放到{}里
    BEGIN{}里的指令,是在读取文件之前,执行1次
    {}里的指令,在读取文件过程中执行,执行N次
    END{}里的指令,是在读取文件之后,执行1次

    # awk -F: 'BEGIN{print "用户名 UID 家目录"} {print $1" "$2" "$3} END{print "总用户 量:"NR}' /opt/a.txt
    这个可以在执行这个文本之前打印BEGIN{}、END{}里面的内容

    # awk 'BEGIN{x=0} /bash$/{x++} END{print x}' /etc/passwd    打印出以bash结尾的用户数量,可以登录的用户,按行读取,读一次bash结尾的数值,x加一次1
    3
    # awk 'BEGIN{x=0} /nologin$/{x++} END{print x}' /etc/passwd   打印出以nologin结尾的用户数量,不可以登录的用户
    38
    awk里面BEGIN{x=0}可以不定义,默认x值为0

    -F指定分隔符
    awk -F: '{print $1}' /etc/passwd   #指定':'为分隔符
    awk -F, '{print $1}' /etc/passwd   #指定','为分隔符

    awk '/正则/{指令}'  文件
    df |awk '//$/{print $4}'  #打印以/结尾的行的第四列

    查看远程登录本机日志
    # tailf /var/log/srcure

    过滤查看正在占用的内存
    # awk '/Failed/{print $11}' /var/log/secure    #过滤出尝试破解密码的IP地址
    # free |awk '/Mem/{print $3}' 

    过滤查看正在占用的CPU使用率[1分钟,5分钟,15分钟]
    # uptime
     20:43:58 up 24 min,  3 users,  load average: 0.00, 0.03, 0.09
    # uptime |awk '{print $10}'      #打印5分钟的cpu使用率
    0.03,

    awk [选项] '条件{指令}'  文件

    条件:
    1、/正则/  awk '/root/' /etc/passwd

    # awk -F: '/root/' /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    operator:x:11:0:operator:/root:/sbin/nologin

    # awk -F: '$1~/root/' /etc/passwd    #~表示正则匹配,$1表示第一列,匹配第一列里面有root的行,打印出来
    root:x:0:0:root:/root:/bin/bash

    # awk -F: '$7!~/bash$/' /etc/passwd   #!~表示正则匹配第7列不是以bash结尾的行,打印出来
    # awk -F: '$7~/bash$/{print $1}' /etc/passwd  #表示将passwd里面能登录的用户,打印出来

    2、字串和数字比较==、!=、<、<=、>、>=   (精确匹配)
    awk -F:'$1=="root"'  /etc/passwd  #将root用户打印出来
    awk -F:'$3<=10'  /etc/passwd      #将UID小于等于10的用户打印出来,UID<=1000即系统用户
    # awk -F: '$3<=10' /etc/passwd    #将UID大于等于1000的用户打印出来,UID>=1000即普通用户
    # awk 'NR==2{print}' /etc/passwd  #输出第2行文本
    # awk 'NF>=6{print}' /etc/passwd  #输出列数大于或等于6的行
    # awk '$2!="XX"{print}' /etc/passwd  #输出第2行文本不是XX的行
    # awk '/^(127|192)/' /etc/hosts    #输出开头是127或192开头的行

    3、逻辑判断&& ||
    # awk -F: '$3>10 && $3<20' /etc/passwd
    # awk -F: '$3==0 || $3==1000' /etc/passwd

    4、算术运算
       能被7整除或包含7的数(1--200)
    # seq 200|awk '$1%7==0 || $1~/7/'    #$1~/7/用到正则模糊匹配,这个数列只有1列所以是$1,匹配含有7的选项

    awk 'BEGIN{x=0;print x%8}'
    awk 'BEGIN{x=0;print x+8}'
    awk 'BEGIN{x=0;print x-8}'
    awk 'BEGIN{x=0;print x*8}'
    awk 'BEGIN{x=0;print x/8}'

    awk 支持if语句
    if (判断){指令}
    if (判断){指令}else {指令}
    if (判断){指令}else if (){指令}

    统计系统用户和普通用户分别是多少(1000)
    awk -F: '{} END{print x,y}' /etc/passwd   #这里可以将if条件句分出来写,然后再复制进去,以防止括号太多导致错误
    if($3>=1000){x++}else{y++}
    最终结果:awk -F: '{if ($3>=1000){x++} else{y++}} END{print x,y}' /etc/passwd

    正则:
          /正则/                对整行匹配
       $n~/正则/           对某一列匹配
       $1~/root/     对第一列匹配是否包含root

  • 相关阅读:
    mysql-master-ha 实现mysql master的高可用。
    一个不错的工具版本管理工具
    java的日志知识
    从解决一个java.lang.NoSuchMethodError想到的
    一个单点登录问题的解决
    关于2013年1月21日的DNS故障分析文章
    每日好的资源整理
    mongodb3.4 sharding安装文档
    python 函数
    codis3安装测试
  • 原文地址:https://www.cnblogs.com/baichuanhuihai/p/8258984.html
Copyright © 2020-2023  润新知