AWK 内置函数详解:从简单到巧妙的实际案例
提到 AWK,我们很容易想到它的字段处理功能,比如提取第几列、按行处理等。其实,AWK 的内置函数才是真正的灵魂!无论是字符串操作、数学计算,还是时间处理,AWK 都能通过这些内置函数展现出强大的数据处理能力。今天我们就来聊聊 AWK 内置函数的妙用,并通过实际案例,让你轻松上手。
1. 字符串处理函数
AWK 的字符串函数非常强大,用于文本处理再合适不过了。
1.1 length()
length()
用来计算字符串或行的长度。
例子:统计每行长度
awk '{print "Line:", $0, "Length:", length($0)}' file.txt
输出:
Line: Hello World Length: 11
Line: AWK is great Length: 13
更实用的场景:筛选长度大于 20 的行
awk 'length($0) > 20' file.txt
这会过滤出所有长度大于 20 的行。
1.2 substr(string, start, length)
substr()
用来从字符串中提取子字符串。
例子:提取每行的前 5 个字符
awk '{print substr($0, 1, 5)}' file.txt
如果 file.txt
内容如下:
HelloWorld
AWK is amazing
输出:
Hello
AWK i
实际案例:从日志中提取时间部分
假设有一个日志文件 access.log
:
192.168.1.1 - - [10/Jan/2025:14:00:01] "GET /index.html HTTP/1.1" 200 512
192.168.1.2 - - [10/Jan/2025:14:05:01] "POST /login HTTP/1.1" 200 256
提取日志中的时间:
awk '{print substr($4, 2)}' access.log
这里的 substr($4, 2)
从第 4 列([10/Jan/2025:14:00:01]
)中跳过第一个字符 [
,提取时间。
输出:
10/Jan/2025:14:00:01
10/Jan/2025:14:05:01
1.3 index(string, substring)
index()
返回子字符串在主字符串中的起始位置,如果不存在则返回 0。
例子:检查是否包含某单词
awk 'index($0, "error") {print NR, $0}' log.txt
这会打印出包含单词 “error” 的行号和内容。
1.4 gsub(r, s [, t])
gsub()
是全局替换函数,将字符串 r
替换为 s
。
例子:将文件中的 TAB 替换为空格
awk '{gsub("\t", " "); print}' file.txt
实际案例:统一日期格式
将文件中的日期从 YYYY/MM/DD
转换为 YYYY-MM-DD
:
awk '{gsub(/[0-9]{4}\/[0-9]{2}\/[0-9]{2}/, gensub("/", "-", "g")); print}' dates.txt
2. 数学函数
AWK 的数学函数让我们可以在文本处理中轻松完成统计和计算任务。
2.1 int(x)
int()
返回 x 的整数部分(向下取整)。
例子:对成绩取整
awk '{print $1, int($2)}' scores.txt
2.2 rand()
和 srand(seed)
rand()
生成 0 到 1 的随机数。srand(seed)
设置随机种子。
例子:生成 10 个随机数
awk 'BEGIN {srand(); for (i=1; i<=10; i++) print rand()}'
实际案例:随机抽取一行数据
awk 'BEGIN {srand()} rand() < 0.1 {print $0}' file.txt
2.3 sqrt(x)
sqrt()
返回 x 的平方根。
例子:计算平方根
awk '{print $1, sqrt($2)}' data.txt
2.4 sin(x)
和 cos(x)
sin()
和 cos()
用来计算正弦和余弦值,x 的单位为弧度。
例子:生成简单的正弦波表
awk 'BEGIN {for (i=0; i<=360; i+=30) print i, sin(i * 3.14159 / 180)}'
3. 时间和日期函数
3.1 systime()
systime()
返回当前时间的时间戳(1970 年 1 月 1 日以来的秒数)。
例子:打印当前时间戳
awk 'BEGIN {print systime()}'
3.2 strftime(format, timestamp)
strftime()
根据格式化字符串将时间戳转换为可读时间。
例子:打印当前时间
awk 'BEGIN {print strftime("%Y-%m-%d %H:%M:%S", systime())}'
4. 结合案例
案例 1:统计日志中不同状态码的数量
假设你的 access.log
文件如下:
192.168.1.1 - - [10/Jan/2025:14:00:01] "GET /index.html HTTP/1.1" 200 512
192.168.1.2 - - [10/Jan/2025:14:05:01] "POST /login HTTP/1.1" 404 256
192.168.1.3 - - [10/Jan/2025:14:10:01] "GET /home.html HTTP/1.1" 200 1024
统计每种状态码的数量:
awk '{codes[$9]++} END {for (code in codes) print code, codes[code]}' access.log
输出:
200 2
404 1
案例 2:提取 CSV 文件中特定列的子字符串
假设你有一个 CSV 文件 users.csv
:
1,JohnDoe,2025-01-10
2,AliceSmith,2025-01-11
3,BobBrown,2025-01-12
提取用户名的前 4 个字符:
awk -F, '{print $2, substr($2, 1, 4)}' users.csv
输出:
JohnDoe John
AliceSmith Alic
BobBrown Bob
总结
AWK 的内置函数让我们能够高效地处理各种复杂的文本数据任务。无论是字符串操作、数学计算还是时间处理,AWK 都表现得游刃有余。如果你觉得今天的内容有帮助,赶快试试这些例子吧!当然,如果你有其他好用的技巧,欢迎留言,我们一起交流!