如何用awk/sed按当日日期排序日志行,使当日行始终居首?
日志按日期逻辑排序需求
我的日志文件每行首列为日期时间,格式示例如下:
May 29 23:14:39 Dec 20 19:45:15 Nov 3 13:15:19 Sep 8 10:34:15 Mar 9 18:39:20 Jan 17 19:34:59
我需要实现两个排序规则:
- 当日的日志行始终排在第一行
- 其余日志按日期倒序排列(例如当日是11月5日,首行是11月5日的日志,之后依次是11月4日、3日……10月31日等)
之前使用命令 sed '/reject/!d' file.txt | sort -r -k2,但该命令仅按数字字符排序,而非日期逻辑排序,导致10月31日的日志排在11月3日之后,无法满足需求。
实现方案
可以通过awk将日期转换为可逻辑排序的数值,配合sort完成需求,完整命令如下:
sed '/reject/!d' file.txt | awk -v today=$(date +"%m %d") ' BEGIN { # 建立英文月份到数字的映射 split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec", months, " ") for (i=1; i<=12; i++) { month_num[months[i]] = i } # 拆分当日的月份和日期 split(today, t_arr, " ") t_month = t_arr[1]+0 t_day = t_arr[2]+0 # 定义各月份天数(忽略闰年,需精确可自行调整) days_in_month[1]=31; days_in_month[2]=28; days_in_month[3]=31; days_in_month[4]=30; days_in_month[5]=31; days_in_month[6]=30 days_in_month[7]=31; days_in_month[8]=31; days_in_month[9]=30; days_in_month[10]=31; days_in_month[11]=30; days_in_month[12]=31 } { # 将当前行的英文月份转为数字 curr_month = month_num[$1] curr_day = $2+0 # 标记是否为当日日志 is_today = (curr_month == t_month && curr_day == t_day) ? 1 : 0 # 计算当前日期是当年的第几天 day_of_year = 0 for (i=1; i<curr_month; i++) { day_of_year += days_in_month[i] } day_of_year += curr_day # 输出辅助排序字段+原日志行 print is_today " " (366 - day_of_year) " " $0 }' | sort -k1r -k2n | cut -d' ' -f3-
命令说明
sed '/reject/!d' file.txt:保留原逻辑,过滤出包含reject的日志行awk部分:- 建立月份映射表,解决英文月份无法直接排序的问题
- 计算每行日期的当年天数,用
366 - day_of_year实现日期倒序的数值化映射 - 给当日日志标记特殊标识,确保排序时优先展示
sort -k1r -k2n:先按当日标记倒序(让当日日志排最前),再按日期映射值正序(实现非当日日志的倒序排列)cut -d' ' -f3-:去除辅助排序字段,输出原始日志内容
如果日志包含年份,只需在awk中添加年份处理,将日期转换为年份*10000 + 月份*100 + 日期的数值,调整排序逻辑即可适配跨年份场景。
内容的提问来源于stack exchange,提问作者Dennis
相关产品推荐
相关产品推荐

