• 三剑客之 awk


    初识awk

    AWK是贝尔实验室1977年搞出来的文本出现神器

    之所以叫AWK是因为其取了三位创始人 Alfred AhoPeter Weinberger, 和 Brian Kernighan 的 Family Name 的首字符

    今天这篇文章主要目的还是为了引起大家对 awk 的兴趣,对于这个上古神器还需要大家自行去查阅相关文档去进一步学习

    通常,awk 是以文件的一行为处理单位的,awk 每接受文件的一行,就会执行相应的命令来处理文本

    例如:执行 awk 时,它依次对/etc/passwd 中的每一行执行 print 命令

    awk '{print 1 $0}' /etc/passwd
    
    • 1

    在这里插入图片描述

    过滤

    从 netstat 命令中提取了以下信息作为例子
    在这里插入图片描述

    Proto Recv-Q Send-Q Local-Address          Foreign-Address             State
    tcp        0      0 0.0.0.0:3306           0.0.0.0:*                   LISTEN
    tcp        0      0 0.0.0.0:80             0.0.0.0:*                   LISTEN
    tcp        0      0 127.0.0.1:9000         0.0.0.0:*                   LISTEN
    tcp        0      0 saltedfish.cn:80        124.205.5.146:18245         TIME_WAIT
    tcp        0      0 saltedfish.cn:80        61.140.101.185:37538        FIN_WAIT2
    tcp        0      0 saltedfish.cn:80        110.194.134.189:1032        ESTABLISHED
    tcp        0      0 saltedfish.cn:80        123.169.124.111:49809       ESTABLISHED
    tcp        0      0 saltedfish.cn:80        116.234.127.77:11502        FIN_WAIT2
    tcp        0      0 saltedfish.cn:80        123.169.124.111:49829       ESTABLISHED
    tcp        0      0 saltedfish.cn:80        183.60.215.36:36970         TIME_WAIT
    tcp        0   4166 saltedfish.cn:80        61.148.242.38:30901         ESTABLISHED
    tcp        0      1 saltedfish.cn:80        124.152.181.209:26825       FIN_WAIT1
    tcp        0      0 saltedfish.cn:80        110.194.134.189:4796        ESTABLISHED
    tcp        0      0 saltedfish.cn:80        183.60.212.163:51082        TIME_WAIT
    tcp        0      1 saltedfish.cn:80        208.115.113.92:50601        LAST_ACK
    tcp        0      0 saltedfish.cn:80        123.169.124.111:49840       ESTABLISHED
    tcp        0      0 saltedfish.cn:80        117.136.20.85:50025         FIN_WAIT2
    tcp        0      0 :::22                  :::*                        LISTEN
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    比如说我们想输出例子中的第一列和第四列

    • $n:表示第几列($0表示整个内容)
    • 执行的操作只能是单引号
    awk '{print $1, $4}' test.txt
    
    • 1
    Proto Local-Address
    tcp 0.0.0.0:3306
    tcp 0.0.0.0:80
    tcp 127.0.0.1:9000
    tcp saltedfish.cn:80
    tcp saltedfish.cn:80
    tcp saltedfish.cn:80
    tcp saltedfish.cn:80
    tcp saltedfish.cn:80
    tcp saltedfish.cn:80
    tcp saltedfish.cn:80
    tcp saltedfish.cn:80
    tcp saltedfish.cn:80
    tcp saltedfish.cn:80
    tcp saltedfish.cn:80
    tcp saltedfish.cn:80
    tcp saltedfish.cn:80
    tcp saltedfish.cn:80
    tcp :::22
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    加上过滤条件

    1、过滤条件:第一列的值为 tcp && 第六列的值为 LISTEN

    awk '$1=="tcp" && $6=="LISTEN"' test.txt
    
    • 1

    2、过滤条件:第三列的值大于等于1,打印过滤出的内容

    awk '$3>=1 {print$0}' test.txt
    
    • 1

    常用的比较运算符

    ==:等于
    !=:不等于
    >:大于
    <: 
    >=:
    <=:
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    指定分隔符

    • 默认是以空格作为分隔符
    • -F 参数:指分隔符

    1、以空格作为分隔符,打印出第四列内容

    awk '{print $4}' test.txt
    或者
    awk -F ' ' '{print $4}' test.txt
    
    • 1
    • 2
    • 3
    Local-Address
    0.0.0.0:3306
    0.0.0.0:80
    127.0.0.1:9000
    saltedfish.cn:80
    saltedfish.cn:80
    saltedfish.cn:80
    saltedfish.cn:80
    saltedfish.cn:80
    saltedfish.cn:80
    saltedfish.cn:80
    saltedfish.cn:80
    saltedfish.cn:80
    saltedfish.cn:80
    saltedfish.cn:80
    saltedfish.cn:80
    saltedfish.cn:80
    saltedfish.cn:80
    :::22
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    2、以 “:” 作为分隔符,打印出第二列内容

    awk -F ':' '{print $2}' test.txt
    
    • 1
    3306           0.0.0.0
    80             0.0.0.0
    9000         0.0.0.0
    80        124.205.5.146
    80        61.140.101.185
    80        110.194.134.189
    80        123.169.124.111
    80        116.234.127.77
    80        123.169.124.111
    80        183.60.215.36
    80        61.148.242.38
    80        124.152.181.209
    80        110.194.134.189
    80        183.60.212.163
    80        208.115.113.92
    80        123.169.124.111
    80        117.136.20.85
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    3、如果要指定多个分隔符,可以这样:

    awk -F '[;:]'
    
    • 1

    awk 内置变量

    $0当前记录(这个变量中存放着整个行的内容)
    1   1~ 1 n当前记录的第n个字段,字段间由FS分隔
    FS输入字段分隔符 默认是空格或Tab
    NF当前记录中的字段个数,就是有多少列
    NR已经读出的记录数,就是行号,从1开始,如果有多个文件话,这个值也是不断累加中。
    FNR当前记录数,与NR不同的是,这个值会是各个文件自己的行号
    RS输入的记录分隔符, 默认为换行符
    OFS输出字段分隔符, 默认也是空格
    ORS输出的记录分隔符,默认为换行符
    FILENAME当前输入文件的名字

    1、我们对输出结果加上行号(过滤条件:第三列的值大于1)

    awk '$3>=1 {print NR,$0}' test.txt
    
    • 1
    1 $ cat netstat.txt
    2 Proto Recv-Q Send-Q Local-Address          Foreign-Address             State
    13 tcp        0   4166 saltedfish.cn:80        61.148.242.38:30901         ESTABLISHED
    14 tcp        0      1 saltedfish.cn:80        124.152.181.209:26825       FIN_WAIT1
    17 tcp        0      1 saltedfish.cn:80        208.115.113.92:50601        LAST_ACK
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2、忽略第一行(即 NR>1)

    awk '$3>=1 && NR>1 {print NR,$0}' test.txt
    
    • 1
    2 Proto Recv-Q Send-Q Local-Address          Foreign-Address             State
    13 tcp        0   4166 saltedfish.cn:80        61.148.242.38:30901         ESTABLISHED
    14 tcp        0      1 saltedfish.cn:80        124.152.181.209:26825       FIN_WAIT1
    17 tcp        0      1 saltedfish.cn:80        208.115.113.92:50601        LAST_ACK
    
    • 1
    • 2
    • 3
    • 4

    3、输出字段以 tab 分隔(以 /etc/passwd 为例)

    字段分隔符默认是空格

    awk -F ':' '{print $1,$3} ' /etc/passwd
    
    • 1
    root 0
    bin 1
    daemon 2
    adm 3
    lp 4
    sync 5
    shutdown 6
    halt 7
    mail 8
    operator 11
    games 12
    ftp 14
    nobody 99
    systemd-network 192
    dbus 81
    polkitd 999
    sshd 74
    postfix 89
    chrony 998
    tss 59
    ntp 38
    tcpdump 72
    zabbix 997
    minion2 1000
    nginx 996
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    指定为 tab

    awk -F ':' '{print $1,$3} ' OFS='\t' /etc/passwd
    
    • 1
    root    0
    bin     1
    daemon  2
    adm     3
    lp      4
    sync    5
    shutdown        6
    halt    7
    mail    8
    operator        11
    games   12
    ftp     14
    nobody  99
    systemd-network 192
    dbus    81
    polkitd 999
    sshd    74
    postfix 89
    chrony  998
    tss     59
    ntp     38
    tcpdump 72
    zabbix  997
    minion2 1000
    nginx   996
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    4、输出记录以 tab 分隔(以 /etc/passwd 为例)

    记录(行)分隔符默认是换行符

    awk -F ':' '{print $1,$3} '  /etc/passwd
    
    • 1
    root 0
    bin 1
    daemon 2
    adm 3
    lp 4
    sync 5
    shutdown 6
    halt 7
    mail 8
    operator 11
    games 12
    ftp 14
    nobody 99
    systemd-network 192
    dbus 81
    polkitd 999
    sshd 74
    postfix 89
    chrony 998
    tss 59
    ntp 38
    tcpdump 72
    zabbix 997
    minion2 1000
    nginx 996
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    指定为 tab

    awk -F ':' '{print $1,$3} ' ORS="\t" /etc/passwd
    
    • 1
    root 0  bin 1   daemon 2        adm 3   lp 4    sync 5  shutdown 6      halt 7  mail 8  operator 11     games 12        ftp 14  nobody 99 systemd-network 192      dbus 81 polkitd 999     sshd 74 postfix 89      chrony 998      tss 59  ntp 38  tcpdump 72      zabbix 997      minion2 1000       nginx 996
    
    • 1

    正则

    在这里插入图片描述
    字符串匹配

    ~ 表示模式开始、/ /中是模式。这就是一个正则表达式的匹配

    1、匹配 LISTEN

    awk '$6 ~ /LISTEN/ {print $0}' test.txt
    
    • 1
    tcp        0      0 0.0.0.0:3306           0.0.0.0:*                   LISTEN
    tcp        0      0 0.0.0.0:80             0.0.0.0:*                   LISTEN
    tcp        0      0 127.0.0.1:9000         0.0.0.0:*                   LISTEN
    tcp        0      0 :::22                  :::*                        LISTEN
    
    • 1
    • 2
    • 3
    • 4

    2、支持模糊匹配

    匹配 LIS 的话,LISTEN 和 EATABLISTED 都会输出

    awk '$6 ~ /LIS/ {print $0}' test.txt
    
    • 1
    tcp        0      0 0.0.0.0:3306           0.0.0.0:*                   LISTEN
    tcp        0      0 0.0.0.0:80             0.0.0.0:*                   LISTEN
    tcp        0      0 127.0.0.1:9000         0.0.0.0:*                   LISTEN
    tcp        0      0 saltedfish.cn:80        110.194.134.189:1032        ESTABLISHED
    tcp        0      0 saltedfish.cn:80        123.169.124.111:49809       ESTABLISHED
    tcp        0      0 saltedfish.cn:80        123.169.124.111:49829       ESTABLISHED
    tcp        0   4166 saltedfish.cn:80        61.148.242.38:30901         ESTABLISHED
    tcp        0      0 saltedfish.cn:80        110.194.134.189:4796        ESTABLISHED
    tcp        0      0 saltedfish.cn:80        123.169.124.111:49840       ESTABLISHED
    tcp        0      0 :::22                  :::*                        LISTEN
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    3、多个匹配条件

    awk '$6 ~ /LISTEN|FIN/{print $0}' test.txt
    
    • 1
    tcp        0      0 0.0.0.0:3306           0.0.0.0:*                   LISTEN
    tcp        0      0 0.0.0.0:80             0.0.0.0:*                   LISTEN
    tcp        0      0 127.0.0.1:9000         0.0.0.0:*                   LISTEN
    tcp        0      0 saltedfish.cn:80        61.140.101.185:37538        FIN_WAIT2
    tcp        0      0 saltedfish.cn:80        116.234.127.77:11502        FIN_WAIT2
    tcp        0      1 saltedfish.cn:80        124.152.181.209:26825       FIN_WAIT1
    tcp        0      0 saltedfish.cn:80        117.136.20.85:50025         FIN_WAIT2
    tcp        0      0 :::22                  :::*                        LISTEN
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    4、取反匹配

    awk '$6 !~ /LISTEN|FIN/ {print $0}' test.txt
    
    • 1
    $ cat netstat.txt
    Proto Recv-Q Send-Q Local-Address          Foreign-Address             State
    tcp        0      0 saltedfish.cn:80        124.205.5.146:18245         TIME_WAIT
    tcp        0      0 saltedfish.cn:80        110.194.134.189:1032        ESTABLISHED
    tcp        0      0 saltedfish.cn:80        123.169.124.111:49809       ESTABLISHED
    tcp        0      0 saltedfish.cn:80        123.169.124.111:49829       ESTABLISHED
    tcp        0      0 saltedfish.cn:80        183.60.215.36:36970         TIME_WAIT
    tcp        0   4166 saltedfish.cn:80        61.148.242.38:30901         ESTABLISHED
    tcp        0      0 saltedfish.cn:80        110.194.134.189:4796        ESTABLISHED
    tcp        0      0 saltedfish.cn:80        183.60.212.163:51082        TIME_WAIT
    tcp        0      1 saltedfish.cn:80        208.115.113.92:50601        LAST_ACK
    tcp        0      0 saltedfish.cn:80        123.169.124.111:49840       ESTABLISHED
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    BEGIN&END

    BEGIN 和 END 这两个关键字意味着执行前和执行后的意思,语法如下:

    • BEGIN{ 这里面放的是执行前的语句 }
    • END {这里面放的是处理完所有的行后要执行的语句 }
    • {这里面放的是处理每一行时要执行的语句}

    以下面内容为例(将 top 输出结果重定向到 top.txt 中)

    USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
    root          1  0.0  0.1 125636  4148 ?        Ss   11月11   0:01 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
    root          2  0.0  0.0      0     0 ?        S    11月11   0:00 [kthreadd]
    root          4  0.0  0.0      0     0 ?        S<   11月11   0:00 [kworker/0:0H]
    root          6  0.0  0.0      0     0 ?        S    11月11   0:00 [ksoftirqd/0]
    root          7  0.0  0.0      0     0 ?        S    11月11   0:00 [migration/0]
    root          8  0.0  0.0      0     0 ?        S    11月11   0:00 [rcu_bh]
    root          9  0.0  0.0      0     0 ?        R    11月11   0:07 [rcu_sched]
    root         10  0.0  0.0      0     0 ?        S<   11月11   0:00 [lru-add-drain]
    root         11  0.0  0.0      0     0 ?        S    11月11   0:00 [watchdog/0]
    root         12  0.0  0.0      0     0 ?        S    11月11   0:00 [watchdog/1]
    root         13  0.0  0.0      0     0 ?        S    11月11   0:00 [migration/1]
    root         14  0.0  0.0      0     0 ?        S    11月11   0:00 [ksoftirqd/1]
    root         16  0.0  0.0      0     0 ?        S<   11月11   0:00 [kworker/1:0H]
    root         18  0.0  0.0      0     0 ?        S    11月11   0:00 [kdevtmpfs]
    root         19  0.0  0.0      0     0 ?        S<   11月11   0:00 [netns]
    root         20  0.0  0.0      0     0 ?        S    11月11   0:00 [khungtaskd]
    root         21  0.0  0.0      0     0 ?        S<   11月11   0:00 [writeback]
    root         22  0.0  0.0      0     0 ?        S<   11月11   0:00 [kintegrityd]
    root         23  0.0  0.0      0     0 ?        S<   11月11   0:00 [bioset]
    root         24  0.0  0.0      0     0 ?        S<   11月11   0:00 [bioset]
    root         25  0.0  0.0      0     0 ?        S<   11月11   0:00 [bioset]
    root         26  0.0  0.0      0     0 ?        S<   11月11   0:00 [kblockd]
    root         27  0.0  0.0      0     0 ?        S<   11月11   0:00 [md]
    root         28  0.0  0.0      0     0 ?        S<   11月11   0:00 [edac-poller]
    root         29  0.0  0.0      0     0 ?        S<   11月11   0:00 [watchdogd]
    root         35  0.0  0.0      0     0 ?        S    11月11   0:00 [kswapd0]
    root         36  0.0  0.0      0     0 ?        SN   11月11   0:00 [ksmd]
    root         37  0.0  0.0      0     0 ?        SN   11月11   0:00 [khugepaged]
    root         38  0.0  0.0      0     0 ?        S<   11月11   0:00 [crypto]
    root         46  0.0  0.0      0     0 ?        S<   11月11   0:00 [kthrotld]
    root         49  0.0  0.0      0     0 ?        S<   11月11   0:00 [kmpath_rdacd]
    root         50  0.0  0.0      0     0 ?        S<   11月11   0:00 [kaluad]
    root         51  0.0  0.0      0     0 ?        S<   11月11   0:00 [kpsmoused]
    root         53  0.0  0.0      0     0 ?        S<   11月11   0:00 [ipv6_addrconf]
    root         66  0.0  0.0      0     0 ?        S<   11月11   0:00 [deferwq]
    root        104  0.0  0.0      0     0 ?        S    11月11   0:00 [kauditd]
    root        283  0.0  0.0      0     0 ?        S<   11月11   0:00 [mpt_poll_0]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    1、计算每个用户的进程占了多少内存

    awk 'NR!=1{a[$1]+=$6;} END { for(i in a) print i ", " a[i]"KB";}' top.txt
    
    • 1
    chrony, 1860KB
    nginx, 3688KB
    dbus, 2492KB
    polkitd, 14152KB
    root, 208636KB
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2、统计当前目录下文件所占空间大小

    ll -h | awk 'BEGIN {size=0} {size=size+$5} END{print size "KB"}'
    
    • 1

    3、统计 /etc/passwd 中用户数量

    awk '{count++} END{print count}' /etc/passwd
    
    • 1

    4、统计有多少条 tcp 连接

    (减掉 2 是因为前面两条字段不是 tcp 连接)

    在这里插入图片描述

    netstat -tnlp | awk '{count++} END{print count-2}'
    
    • 1

    5、打印出 11日到12日 13点到14点之间的日志信息
    在这里插入图片描述

    awk '{if ($2>10 && $2<12 && $3>"13:00:00" && $3<"14:00:00") print}' /var/log/messages
    
    • 1
  • 相关阅读:
    QT-MySQL QSqlDatabase: QMYSQL driver not loaded
    UML中用例和用例图的概念
    818专业课【考经】—《信号系统》之章节概要:第五章 连续时间信号的变换域分析
    K8S Calico网络插件
    Linux常用命令
    java二手车商城计算机毕业设计MyBatis+系统+LW文档+源码+调试部署
    # CSP-J 2023 第一轮试题
    linux 环境下 分布式文件搭建fastDFS
    图神经网络关系抽取论文阅读笔记(六)
    【黑马-SpringCloud技术栈】【02】服务拆分及远程调用_服务提供者与消费者
  • 原文地址:https://blog.csdn.net/s_alted/article/details/127840842