如何通过Shell脚本基于AM/PM对日期时间字段排序?
问题:sort命令无法识别AM/PM导致日期时间排序错误
我尝试用sort -t',' -k2,2 -k7,7r file.csv对CSV数据按第7列的日期时间反向排序,但命令没识别AM/PM,导致排序结果不对——10 AM的行居然排在2 PM的行前面,顺序完全没变。
排序前的原始数据:
field1,field2,field3,field4,field5,field6,19-NOV-23 10.58.03.000000 AM field1,field2,field3,field4,field5,field6,19-NOV-23 02.48.47.000000 PM
执行命令后得到的结果(不符合预期):
field1,field2,field3,field4,field5,field6,19-NOV-23 10.58.03.000000 AM field1,field2,field3,field4,field5,field6,19-NOV-23 02.48.47.000000 PM
原因分析
默认情况下sort是按字符串字典序排序的,"10"开头的字符串比"02"大,所以10 AM的行被判定为“更大”,排在前面。而且sort本身不会自动解析AM/PM来转换为24小时制时间进行比较。
解决方案
方法1:用awk转换为24小时制后排序(通用所有环境)
通过awk把12小时制时间转成24小时制,生成一个临时的排序键,排序后再去掉这个键,就能得到正确结果:
awk -F',' '{ split($7, dt_parts, /[ .]/) hour = dt_parts[3] ampm = dt_parts[7] # 转换小时到24制 if (ampm == "PM" && hour != "12") hour += 12 else if (ampm == "AM" && hour == "12") hour = "00" # 生成排序用的24制时间键 sort_key = dt_parts[1] " " sprintf("%02d", hour) ":" dt_parts[4] ":" dt_parts[5] print sort_key "," $0 }' file.csv | sort -t',' -k1,1r | cut -d',' -f2-
执行后会输出正确的反向排序结果:
field1,field2,field3,field4,field5,field6,19-NOV-23 02.48.47.000000 PM field1,field2,field3,field4,field5,field6,19-NOV-23 10.58.03.000000 AM
方法2:用GNU sort的时间解析功能(仅适用于GNU sort)
如果你用的是GNU版sort(大部分Linux系统默认是这个),可以直接指定时间格式让sort自动解析AM/PM:
sort -t',' --time-format="%d-%b-%y %I.%M.%S.%6N %p" -k7,7r file.csv
这个命令里--time-format定义了输入时间的格式,sort会按照实际时间值来排序,自然就能识别AM/PM的区别。
内容的提问来源于stack exchange,提问作者MuhammedF
相关产品推荐
相关产品推荐

