我有一个日志文件的条目如:
... freeswitch.log:2011-09-08 12:21:07.282236 [ERR] ftdm_queue.c:136 Failed to enqueue obj 0x7f2cda3525c0 in queue 0x7f2ce8005990, no more room! windex == rindex == 58! freeswitch.log:2011-08-08 13:21:07.514261 [ERR] ftdm_queue.c:136 Failed to enqueue obj 0x7f2cda354460 in queue 0x7f2ce8005990, no more room! windex == rindex == 58! freeswitch.log:2011-06-04 16:21:08.998227 [ERR] ftdm_queue.c:136 Failed to enqueue obj 0x7f2cda356300 in queue 0x7f2ce8005990, no more room! windex == rindex == 58! freeswitch.log:2011-09-08 12:21:10.374238 [ERR] ftdm_queue.c:136 Failed to enqueue obj 0x7f2cda3581a0 in queue 0x7f2ce8005990, no more room! windex == rindex == 58! ...
我怎样才能sorting文件与Linux命令行工具的时间戳在每一行降?
使用排序的-k标志:
sort -k1 -r freeswitch.log
这将按照第一个键(即freeswitch.log:2011-09-08 12:21:07.282236)对文件进行反向排序。 如果文件名总是相同的(freeswitch.log),那么它应该按日期排序。
使用sort的--stable
,– --reverse
和--key
选项:
sort --stable --reverse --key=1,2 freeswitch.log
(对于非教学目的,这可以缩写为-srk1,2
。
sort
命令(如您所期望的)按排序顺序输出命名文件(或STDIN)的每一行。 这些选项各有什么作用:
--reverse
选项告诉sort
行的更高值(更晚的日期) 更高 ,而不是更低。 根据其他答案,假定这就是“降序”(即使这种排序通常被认为是“上升”)。 如果要按时间顺序对行进行排序,则会省略此选项。 --key=1,2
选项告诉sort
只使用前两个以空格分隔的“fields”(“freeswitch.log:” – 前缀日期和时间)作为排序的关键字。 即使只按一个字段排序(例如,如果每行在ISO-8601标准字段中保存时间和日期,例如freeswitch.log 2011-09-08T12:21:07.282236
,则指定最后一个字段也是很重要的freeswitch.log 2011-09-08T12:21:07.282236
,你可以使用-k 2,2
),因为默认情况下,一个键使用的字段会延伸到行尾 。 --stable
选项告诉sort
不执行“最后手段排序”。 如果没有这个选项,那么带有两个相等键的行(用--keys
选项指定)将按照整行进行排序,这意味着文件名和/或内容将改变行的排序顺序。 指定--key
两个范围以及--stable
选项非常重要。 没有它们,同时发生的多行输出(换句话说,多行消息)将根据消息的内容(没有--key
的第二个字段)和/或文件名(没有--stable
,如果文件名是一个单独的字段,如下所述)。
换句话说,像这样的日志消息:
freeswitch.log:2011-09-08 12:21:10.374238 Warning: Syntax error on line 20: freeswitch.log:2011-09-08 12:21:10.374238 freeswitch.log:2011-09-08 12:21:10.374238 My[brackets(call) freeswitch.log:2011-09-08 12:21:10.374238 ^ freeswitch.log:2011-09-08 12:21:10.374238 Suggestion: freeswitch.log:2011-09-08 12:21:10.374238 did you forget to freeswitch.log:2011-09-08 12:21:10.374238 close your brackets?
将被“排序”为:
freeswitch.log:2011-09-08 12:21:10.374238 freeswitch.log:2011-09-08 12:21:10.374238 ^ freeswitch.log:2011-09-08 12:21:10.374238 close your brackets? freeswitch.log:2011-09-08 12:21:10.374238 did you forget to freeswitch.log:2011-09-08 12:21:10.374238 My[brackets(call) freeswitch.log:2011-09-08 12:21:10.374238 Suggestion: freeswitch.log:2011-09-08 12:21:10.374238 Warning: Syntax error on line 20:
这是“排序” (因为“c”在“d”之前,“S”在“W”之前),但是不是按顺序排列的 。 指定--stable
(并保持你的--key
有界)将跳过额外的排序,并保持顺序 ,这是你想要的。
此外,通过这个组合的文件名和日期字段进行排序只有在输出中的每一行都以相同的文件名开始时才有效。 鉴于你发布的语法,如果你的输入有多个不同的文件名,你想在排序中忽略,你需要使用像sed
这样的程序将文件名转换为它自己的空格分隔的字段,然后管道转换后的行进行sort
之后你可以转换字段分隔符):
sed 's/:/ /' freeswitch.log | sort -srk2,3 | sed 's/ /:/'
请注意,密钥使用的字段被更改为2,3
,跳过第一个(文件名)字段。
你可以通过反转来排序
sort -r
你可以尝试使用排序
sort -k1,2 file
粗糙而有效的技术:在每行前面添加日期的数字表示,按数字排序,然后删除额外的信息。
Oneliner:
while IFS=' ' read -r name_date trailing ; do date=$(cut -d: -f2 <<<"$name_date") ; printf '%s:%s\n' $(date -d "$date" +%s) "$name_date $trailing" ; done < freeswitch.log | sort -k1 -t: | cut -d: -f2-
Shell脚本:
#!/usr/bin/env bash logfile="$1" if [ -f "$logfile" ] ; then while IFS=' ' read -r name_date trailing ; do date=$(cut -d: -f2 <<<"$name_date") printf '%s:%s\n' $(date -d "$date" +%s) "$name_date $trailing" done < "$logfile" | sort -k1 -t: | cut -d: -f2- fi
注意:需要GNU日期。
如果此时的输出与您想要的相反,则通过tac
传输或修改脚本以传递-r
进行sort
也很简单。
编辑:我错过了每一行字面上的文件名的部分。 现在更新版本实际上工作。
日志文件似乎上升,你可以
tac yourlogfile
这将反向显示您的日志文件。
我猜日志文件在最后附加了新的数据。 如果是这样,你可以反向读取文件。 尝试使用tail -r或cat命令。