三剑客之 awk

本文介绍了awk命令的基础用法,包括文本过滤、内置变量、比较运算符和正则表达式等。通过实例展示了如何提取特定列、设置过滤条件以及改变分隔符,还探讨了BEGIN和END块的应用,是学习awk命令的好起点。
摘要由CSDN通过智能技术生成

初识awk

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

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

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

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

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

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

在这里插入图片描述

过滤

从 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

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

  • $n:表示第几列($0表示整个内容)
  • 执行的操作只能是单引号
awk '{print $1, $4}' test.txt
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、过滤条件:第一列的值为 tcp && 第六列的值为 LISTEN

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

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

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

常用的比较运算符

==:等于
!=:不等于
>:大于
<: 
>=:
<=:

指定分隔符

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

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

awk '{print $4}' test.txt
或者
awk -F ' ' '{print $4}' test.txt
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

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

awk -F ':' '{print $2}' test.txt
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

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

awk -F '[;:]'

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 $ 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

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

awk '$3>=1 && NR>1 {print NR,$0}' test.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

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

字段分隔符默认是空格

awk -F ':' '{print $1,$3} ' /etc/passwd
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

指定为 tab

awk -F ':' '{print $1,$3} ' OFS='\t' /etc/passwd
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

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

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

awk -F ':' '{print $1,$3} '  /etc/passwd
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

指定为 tab

awk -F ':' '{print $1,$3} ' ORS="\t" /etc/passwd
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、匹配 LISTEN

awk '$6 ~ /LISTEN/ {print $0}' test.txt
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

2、支持模糊匹配

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

awk '$6 ~ /LIS/ {print $0}' test.txt
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

3、多个匹配条件

awk '$6 ~ /LISTEN|FIN/{print $0}' test.txt
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

4、取反匹配

awk '$6 !~ /LISTEN|FIN/ {print $0}' test.txt
$ 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

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、计算每个用户的进程占了多少内存

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

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

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

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

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

4、统计有多少条 tcp 连接

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

在这里插入图片描述

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

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

awk '{if ($2>10 && $2<12 && $3>"13:00:00" && $3<"14:00:00") print}' /var/log/messages
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咸鱼Linux运维

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值