awk 这个命令之前见过几次,但是就是不会用;上大学时 Linux 课程中老师同样讲过这个命令,可惜怎么用不记得了,梗还记着:awk —— Awkward。昨天做 Vulnhub 正好碰见,就学习下了。
awk 是一个强大的文本处理程序,它逐行处理每一个字段,即可以方便地处理包含固定个字段的文本数据 (与一张 Excel 表格类似)。整个处理过程由规则控制,规则被大括号包围,而所有的规则又被单引号 (') 包围。
字段选择
awk 最常用的方式便是显示特定的字段,日志处理中较常用。比如我们需要查看 /etc 文件夹的内容:
1
2
3
4
5
6
7
8
9
10
11
12
|
ls -lh /etc
drwxr-xr-x 3 root root 38 7月 23 21:12 acpi
-rw-r--r-- 1 root root 44 2月 19 02:16 adjtime
drwxr-xr-x 3 root root 20 9月 11 2019 alsa
-rw-r--r-- 1 root root 541 11月 1 2019 anacrontab
drwxr-xr-x 2 root root 126 7月 23 21:12 apparmor
drwxr-xr-x 7 root root 163 7月 23 21:12 apparmor.d
lrwxrwxrwx 1 root root 15 5月 21 15:30 arch-release -> manjaro-release
drwxr-xr-x 3 root root 92 2月 19 02:36 audisp
drwxr-xr-x 2 root root 49 2月 19 02:36 audit
drwxr-xr-x 3 root root 117 3月 26 19:49 avahi
|
但是我们只需要权限信息和文件名称,便可以使用以下的命令:
1
2
3
4
5
6
7
8
9
10
11
12
|
ls -lh /etc | awk '{print $1,$NF}'
drwxr-xr-x acpi
-rw-r--r-- adjtime
drwxr-xr-x alsa
-rw-r--r-- anacrontab
drwxr-xr-x apparmor
drwxr-xr-x apparmor.d
lrwxrwxrwx manjaro-release
drwxr-xr-x audisp
drwxr-xr-x audit
drwxr-xr-x avahi
|
很直观,第一个字段用 $1 表示,第 n 个字段就用 $n 表示,多个字段之间用英文逗号隔开。这里有一个比较特殊的用法,$NF 表示最后一个字段,这里的 NF 代表 number of field。同样的,$(NF-1) 表示倒数第二个字段。
分隔符选择
awk 默认读入的内容依靠空白字符分隔字段,而输出的分隔默认为空格,当然默认是可以替换的。
输出分隔
例如之前的案例,我们需要把输出的两个字段之间的分隔改称":",在规则中指定:
1
2
3
4
5
6
7
8
9
10
11
12
|
ls -lh /etc | awk 'OFS=":" {print $1,$NF}'
drwxr-xr-x:acpi
-rw-r--r--:adjtime
drwxr-xr-x:alsa
-rw-r--r--:anacrontab
drwxr-xr-x:apparmor
drwxr-xr-x:apparmor.d
lrwxrwxrwx:manjaro-release
drwxr-xr-x:audisp
drwxr-xr-x:audit
drwxr-xr-x:avahi
|
输入分隔
假如要解析的文件是 /etc/passwd,需要查看用户名和默认的 shell,但该文件不同字段间是用 “:” 分隔的,-F 参数来指定输入的分隔符,使用如下的命令:
1
2
3
4
5
6
7
8
|
cat /etc/passwd | awk -F: '{print $1,$NF}'
root /bin/bash
nobody /usr/bin/nologin
dbus /usr/bin/nologin
bin /usr/bin/nologin
daemon /usr/bin/nologin
mail /usr/bin/nologin
|
BEGIN 和 END 规则
BEGIN 规则在读取处理文本前执行且只执行一次,END 规则在所有的文本处理结束之后执行一次,当然这两个规则是独立于文本处理规则的。有一个比较实用的用处,BEGIN 规则打印表头,END 规则打印表尾,这样就可以使表的结构更加完整。继续举上面的例子:
1
2
3
4
5
6
7
8
9
10
11
|
cat /etc/passwd | awk -F: 'BEGIN {print " User & shell\n----------------------"} {print $1,$NF} END {print "----------------------"}'
User & shell
----------------------
root /bin/bash
nobody /usr/bin/nologin
dbus /usr/bin/nologin
bin /usr/bin/nologin
daemon /usr/bin/nologin
mail /usr/bin/nologin
----------------------
|
条件判断
awk 文本处理过程可以加入条件判断,可以是简单的条件语句,也能是复杂的 if else 分支语句。
简单条件
假设需要查看 uid 大于等于 1000 的用户和 shell 环境:
1
2
3
4
|
cat /etc/passwd | awk -F: '$3 >= 1000 {print $1, $NF}'
nobody /usr/bin/nologin
haha /bin/zsh
|
内置函数
awk 提供了许多 内置函数,例如数值计算、大小写转换、执行系统命令等。
执行系统命令
1
2
3
|
awk 'BEGIN {system("echo hello")}'
hello
|
当然,我们可以用 awk 弹 shell,如果 awk 有 suid 权限,则可以来提权:
1
|
awk 'BEGIN {system("/bin/sh")}'
|
数值计算
1
2
3
|
awk 'BEGIN {print sqrt(625)}'
25
|
输出转化为大写
1
2
3
4
|
cat /etc/passwd | awk -F: '$3 >= 1000 {print toupper($1), $NF}'
NOBODY /usr/bin/nologin
HAHA /bin/zsh
|
参考文档
- https://www.howtogeek.com/562941/how-to-use-the-awk-command-on-linux/
- http://www.ruanyifeng.com/blog/2018/11/awk.html