文本处理三剑客之awk

awk 是一个文本处理工具,通常用于处理数据并生成结果报告。

awk 的工作模式和 sed 类似,也是逐行读取,逐行处理。

1
2
3
4
5
awk [-W option] [-F value] [-v var=value] [--] 'program text' [file ...]
awk [-W option] [-F value] [-v var=value] [-f program-file] [--] [file ...]

-F # 指定分隔符
-v # 变量赋值

语法格式

1
2
3
awk 'BEGIN{commands}pattern{commands}END{commands}' file
# 或
standard output | awk 'BEGIN{commands}pattern{commands}END{commands}'
  • BEGIN{commands}:正式处理文本之前执行,可以省略
  • END 后{commands}:处理完所有文本后执行,可以省略
  • pattern{commands}:逐行执行,pattern 判断此行是否符合匹配模式,符合则执行{commands}
    • pattern:匹配模式,可以省略
    • {commands}:对每行执行的命令,这里面可以写判断、循环等语句,功能强大,所以 awk 又被称为 awk 编程。不可省略

内置变量

1
2
3
4
5
6
7
8
9
10
11
12
$0          # 整行内容
$1 - $n # 当前行的第1-n个字段
NF # 当前行的字段个数,也就是有多少列
NR # 当前行的行号,从1开始计数
FNR # 多文件处理时,每个文件行号单独计数,从0开始
FS # 输入字段分割符。不指定默认就是空格或tab
RS # 输入行分割符号。默认回车换行
OFS # 输出字段分隔符。默认空格
ORS # 输出行分割符。默认回车换行
FILENAME # 处理文件的文件名
ARGC # 命令行参数个数
ARGV # 命令行参数数组

格式化输出 printf

格式符

1
2
3
4
5
6
7
%s    # 打印字符串
%d # 打印十进制数
%f # 打印一个浮点数
%x # 打印十六进制数
%o # 打印八进制数
%e # 打印数字的科学计数法形式
%c # 打印单个字符的ASCII码

修饰符

1
2
3
-    # 左对齐
+ # 右对齐
# # 显示八进制在前面加0,显示十六进制在前面加0x

模式匹配

第一种模式匹配:正则表达式 RegExp

第二种模式匹配:关系运算符号匹配

<、>、<、>=、!=
:匹配正则表达式
!
:不匹配正则表达式
||:或
&&:与
!:非

表达式

+、-、、/、%、^或*、++x、x++、–x、x–

-x:转换为负数
+x:将字符串转换为数值

条件语句

注:awk 中语句块没有作用域,都是全局变量。

1
2
3
4
5
6
if(条件表达式)
动作1
else if(条件表达式)
动作2
else
动作3
1
2
3
4
5
switch (expression) {
case value|regex : statement
...
[ default: statement ]
}

循环语句

1
2
while(条件表达式)
动作
1
2
3
do
动作
while(条件表达式)
1
2
for(i=0; i<100, i++)
动作

continue 和 break

continue 跳过本次循环,break 跳出整个循环

next

next 可以提前结束对本行处理而直接进入下一行处理(awk 自身循环)

1
[root@centos8 ~]#awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd

awk 内置函数

算数函数

  • rand:返回 0-1 之间一个随机数,需要配合 srand()配合生成随机数种子

    1
    [root@centos8 ~]#awk 'BEGIN{srand();print rand()}'
  • int:返回整数

字符串函数

  • length

  • index

  • tolower

  • toupper

  • substr

  • split

  • match

  • sub

  • gsub

时间函数

  • mktime:生成时间戳

  • strftime:将时间戳转化格式化时间输出

    1
    strftime("%Y-%m-%dT%H:%M",systime()) ;
  • systime:获取当前时间戳

其他函数

  • next:提前结束本行处理,进入下一行处理

  • system:system(commands),在 awk 中调用 shell 命令

  • exit

终止脚本执行

常用选项

1
2
3
4
-v    # 参数传递
-f # 指定脚本文件
-F # 指定分割符
-V # 查看awk的版本号

数组

shell 中数组的下标从 0 开始,awk 中数组下标从 1 开始,而且也有关联数组。但每次只能定义元素。如果想一次性定义多个元素,可以通过 split 间接实现。

1
2
3
4
str="a b c d e"
split(str,array," ")
for(i in array)
print array[i]

++

awk 中,数组[键]++ 表示给数组的元素赋值,赋值+1。灵活运用,可以实现去重、统计的功能

1
2
3
4
arr[a]=1
arr[b]=2

print arr[a]++ # 2

范例:显示主机的连接状态出现的次数

1
2
awk 'NR!=1{print $1}' ss.log |sort |uniq -c
ss -ant | awk 'NR>1 {++s[$1]} END {for(k in s) print k,s[k]}'

awk

脚本

将 awk 写成脚本,调用或直接执行

范例:调用

1
2
3
4
5
6
7
[root@centos8 ~]#cat passwd.awk
{if($3>=1000)print $1,$3}
[root@centos8 ~]
[root@centos8 ~]#awk -F: -f passwd.awk /etc/passwd
nobody 65534
wang 1000
mage 1001

范例:直接执行

1
2
3
4
5
6
7
8
9
10
[root@centos8 ~]#cat test.awk
#!/bin/awk -f
#this is a awk script
{if($3>=1000)print $1,$3}
[root@centos8 ~]
[root@centos8 ~]#chmod +x test.awk
[root@centos8 ~]#./test.awk -F: /etc/passwd
nobody 65534
wang 1000
mage 1001

练习:

检查出最近一小时内访问 nginx 服务次数超过 3 次的客户端 IP

1

1、文件 host_list.log 如下格式,请提取”.magedu.com”前面的主机名部分并写入到回到该文件中

1
2
3
4
5
6
7
1 www.magedu.com
2 blog.magedu.com
3 study.magedu.com
4 linux.magedu.com
5 python.magedu.com
......
999 study.magedu.com

2、统计/etc/fstab 文件中每个文件系统类型出现的次数

3、统计/etc/fstab 文件中每个单词出现的次数

4、提取出字符串 Yd$C@M05MB%9&Bdh7dq+YVixp3vpw 中的所有数字

5、有一文件记录了 1-100000 之间随机的整数共 5000 个,存储的格式 100,50,35,89…请取出其中最大和最小的整数

6、解决 Dos 攻击生产案例:根据 web 日志或者或者网络连接数,监控当某个 IP 并发连接数或者短时内 PV 达到 100,即调用防火墙命令封掉对应的 IP,监控频率每隔 5 分钟。防火墙命令为:iptables -AINPUT -s IP -j REJECT

7、将以下文件内容中 FQDN 取出并根据其进行计数从高到低排序

1
2
3
4
5
6
7
http://mail.magedu.com/index.html
http://www.magedu.com/test.html
http://study.magedu.com/index.html
http://blog.magedu.com/index.html
http://www.magedu.com/images/logo.jpg
http://blog.magedu.com/20080102.html
http://www.magedu.com/images/magedu.jpg