AWK 函数调用

《AWK 函数调用》


🎯 学习目标

  • 掌握 AWK 内置函数的使用方法(如 length, substr, index, split 等)
  • 理解如何自定义函数实现模块化脚本编写
  • 能在实际日志分析、系统信息提取中灵活调用函数
  • 提升脚本可读性与复用性,为复杂数据处理打下基础
  • 了解不同 Linux 发行版(Ubuntu、CentOS、EulerOS)对函数支持的差异

🔑 核心重点

类型 函数名 功能说明
字符串操作 length(), substr(), index(), match() 字符串长度、截取、查找、正则匹配
字段分割 split() 将字符串按分隔符拆分为数组
数学运算 int(), sqrt(), rand(), srand() 整数转换、平方根、随机数生成等
时间处理 systime(), strftime() 获取当前时间戳、格式化输出时间
自定义函数 function name(...) { ... } 自定义逻辑封装,提升代码结构

📚 详细讲解


一、内置函数详解

1. 字符串处理函数

length([str])

返回字符串长度,不传参数时默认统计整行 $0

echo "hello world" | awk '{print length(), length($1)}'

输出:

11 5
substr(str, start, [length])

从指定位置开始截取子字符串

awk 'BEGIN{print substr("Linux is awesome", 8, 2)}'

输出:

is
index(str, find)

查找子字符串首次出现的位置(无则返回 0)

awk 'BEGIN{print index("Ubuntu", "bu")}'

输出:

2
match(str, regex)

匹配正则表达式,返回起始位置,并设置 RSTARTRLENGTH

awk 'BEGIN{
    str = "访问IP: 192.168.1.100";
    if (match(str, /[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/))
        print substr(str, RSTART, RLENGTH)
}'

输出:

192.168.1.100

2. 字段分割函数:split()

将字符串按指定分隔符拆分成数组

awk 'BEGIN{
    str = "apple,banana,orange";
    n = split(str, arr, ",");
    for(i=1; i<=n; i++) print arr[i]
}'

输出:

apple
banana
orange

📌 实战应用:提取路径中的用户名

awk -F: '$3 >= 1000 {
    split($6, path, "/");
    print $1, path[3]
}' /etc/passwd

说明:

  • $6 是用户的家目录路径(如 /home/ubuntu
  • path[3] 是用户名(ubuntu)

3. 数学函数

int(x):取整
awk 'BEGIN{print int(3.1415)}'

输出:

3
sqrt(x):平方根
awk 'BEGIN{print sqrt(16)}'

输出:

4
rand():生成 0~1 的随机数

⚠️ 需要先调用 srand() 设置种子

awk 'BEGIN{srand(); print rand()}'

4. 时间处理函数

systime():获取当前时间戳(秒级)
awk 'BEGIN{print systime()}'
strftime(format, timestamp)

格式化输出时间,默认使用当前时间

awk 'BEGIN{
    now = systime();
    print strftime("%Y-%m-%d %H:%M:%S", now)
}'

输出示例:

2025-06-22 23:45:01

⏰ 常用格式符:

  • %Y:年份
  • %m:月份
  • %d:日期
  • %H:小时(24h)
  • %M:分钟
  • %S:秒

二、实战案例:解析 Nginx 日志并格式化输出

场景:提取 IP、请求路径、状态码、时间,并格式化显示

假设日志如下:

192.168.1.100 - - [22/Jun/2025:12:34:56 +0800] "GET /index.html HTTP/1.1" 200 612 "-" "Mozilla/5.0"

我们写一个 AWK 脚本来美化输出:

awk '
{
    # 提取时间字段并格式化
    time_str = substr($4, 2);          # 去掉开头的 [
    split(time_str, t, ":");           # 拆分时间部分
    date_part = t[1];                  # 日期部分:22/Jun/2025
    time_part = t[2] ":" t[3] ":" t[4];# 时间部分:12:34:56

    # 输出格式化日志
    printf "%-15s %-20s %-5s %s\n", $1, $7, $9, time_part
}' access.log

输出示例:

192.168.1.100   /index.html          200   12:34:56

📌 应用场景:

  • 日志归档
  • 审计日志展示
  • 自动化监控报告生成

三、自定义函数:模块化你的脚本逻辑

语法:

function 函数名(参数列表) {
    # 函数体
}

示例:判断是否是普通用户(UID >= 1000)

awk -F: '
function is_normal_user(uid) {
    return uid >= 1000 ? "是" : "否"
}

NR > 1 {
    print $1, is_normal_user($3)
}' /etc/passwd

输出示例:

root 否
daemon 否
ubuntu 是

四、实战案例:统计每个小时内访问量(带函数封装)

awk '
function get_hour(log_time,    t) {
    gsub(/\[|\+.*$/, "", log_time);
    split(log_time, t, ":");
    return t[2];
}

{
    hour = get_hour($4);
    count[hour]++;
}

END {
    for (h in count)
        print h ":00 ~ " h ":59", count[h], "次访问"
}' access.log

输出示例:

12:00 ~ 12:59 150 次访问
13:00 ~ 13:59 200 次访问

📌 技巧说明:

  • 使用了函数封装提取小时逻辑
  • 可以轻松扩展成“每天”、“每周”统计

五、不同 Linux 发行版注意事项(Ubuntu vs CentOS vs EulerOS)

特性 Ubuntu CentOS EulerOS
默认 awk gawk gawk gawk
支持自定义函数
支持 strftime() ✅(gawk)
支持 PROCINFO["sorted_in"] ✅(gawk 4.0+)
日志文件位置 /var/log/syslog /var/log/messages /var/log/messages

📌 小贴士:

  • 在 CentOS/EulerOS 上查看 /var/log/messages 需要管理员权限,建议使用 sudo awk ...
  • 不同系统的日志格式会影响字段提取逻辑,请先观察几行日志结构再写脚本

六、调试与优化建议

技巧 说明
print $0 打印原始行内容,确认是否符合预期
print NF 查看字段数量是否正确
print substr($0, 1, 50) 查看前几个字符,辅助定位字段偏移
`head -n 5 file awk '...'`
BEGIN{FS=","} 设置合适的字段分隔符提升可读性
function debug(...) 自定义调试函数统一输出格式

✅ 总结

掌握 AWK 的函数调用能力,是迈向高级脚本开发的重要一步。通过使用内置函数和自定义函数,你可以:

  • 快速处理文本、提取关键信息
  • 实现复杂的逻辑封装与复用
  • 构建高效、可维护的日志分析工具

无论你是想做服务器日志分析、自动化运维脚本开发,还是系统安全审计,AWK 的函数机制都能为你提供强大支撑。

继续练习真实日志文件,结合 grepsortuniq 等命令,你将成为一名真正的 Linux 文本处理高手!🚀🔥

posted @ 2025-06-22 22:56  红尘过客2022  阅读(58)  评论(0)    收藏  举报