在awk中调用外部命令,在首列前添加星期几信息
解决awk批量处理日期并添加星期几的问题
问题回顾
你有一个存储利用率文件,格式为DD.MM 存储用量(KB),已经能用awk计算相邻行的用量差值并转换为GB,但无法在awk中通过system()批量给日期添加星期几名称。
可行解决方案
方法1:awk调用date命令(通用awk版本)
利用awk的getline捕获外部date命令的输出,替代只能返回退出码的system()。需要注意补全年份(因为DD.MM没有年份,这里默认用当前年份,也可手动指定):
BEGIN { # 获取当前年份,或手动设置为固定值如 year=2024 "date +%Y" | getline year close("date +%Y") } NR>1 { # 拆分DD.MM格式的日期 split($1, date_parts, /\./) # 转换为date命令可识别的YYYY-MM-DD格式 full_date = year "-" date_parts[2] "-" date_parts[1] # 获取星期几全称(%A),用%a可获取缩写如Mon/Tue "date -d '" full_date "' +%A" | getline weekday close("date -d '" full_date "' +%A") # 计算差值并转换为GB,保留2位小数 usage_diff = ($2 - prev_usage) / 1024 / 1024 printf "%s %s %.2f GB\n", weekday, $1, usage_diff } # 保存上一行的存储用量 { prev_usage = $2 }
关键说明:
- 必须用
close()关闭每次调用的管道,避免awk耗尽文件描述符 - 如果日期跨年份,需要将
year变量改为对应年份,或从其他渠道获取年份信息
方法2:GNU awk内置函数(无外部命令,效率更高)
如果你使用GNU awk(gawk),可以直接用内置的mktime()和strftime()函数处理日期,无需调用外部date命令,速度更快:
BEGIN { # 获取当前年份,或手动指定 current_year = strftime("%Y") } { # 拆分日期 split($1, date_parts, /\./) # 构造mktime所需的格式:YYYY MM DD HH MM SS timestamp = mktime(current_year " " date_parts[2] " " date_parts[1] " 00 00 00") # 获取星期几名称 weekday = strftime("%A", timestamp) # 存储当前行的信息 weekdays[NR] = weekday dates[NR] = $1 usages[NR] = $2 } NR>1 { # 计算差值并输出 usage_diff = (usages[NR] - usages[NR-1]) / 1024 / 1024 printf "%s %s %.2f GB\n", weekdays[NR], dates[NR], usage_diff }
方法3:预处理文件后再计算差值
先给原文件的每一行添加星期几,再用awk计算差值,适合需要分步处理的场景:
# 第一步:给每行添加星期几 awk '{ split($1, d, /\./) "date +%Y" | getline y close("date +%Y") full_date = y "-" d[2] "-" d[1] "date -d '" full_date "' +%A" | getline w close("date -d '" full_date "' +%A") print w, $0 }' storage.log > with_weekday.log # 第二步:计算相邻行差值 awk 'NR>1{print $1, $2, ($4 - prev)/1024/1024 " GB"} {prev=$4}' with_weekday.log
示例验证
假设原文件storage.log内容:
01.01 1048576
02.01 2097152
03.01 3145728
运行方法1的命令后,输出:
Monday 02.01 1.00 GB
Tuesday 03.01 1.00 GB
内容的提问来源于stack exchange,提问作者programings
相关产品推荐
相关产品推荐

