我有一个巨大的数据集,其中包含存储在行中的制表符分隔值。示例行如下所示:
Dec 4 14:37:36.381651 algorc1 [27751:l@27932]/error: [] - [T0000A124M5] Didn't receive message!
我想过滤掉特定日期的特定时间之前的所有消息。
我的想法是这样的:
grep <file> | select everything in first column larger than date | select everything in second column larger than time
我只是不知道如何按列进行选择,也不知道更大和更小的日期和时间。
所以我不太了解;-)。
答案1
您可以使用它sed
来过滤这些。这个简单的示例假设您知道确切的开始/结束时间:
sed -n '/Dec 4 14:37:36.381651/,/Dec 5 14:32:36.391572/' filename
您无法将这些时间/日期舍入为不存在的值。例如:
sed -n '/Dec 4 14:30:00.000000/,/Dec 5 14:29:59.999999/' filename
除非指定的时间都在日志中,否则将无法工作。
如果您想在日志中没有的两个任意时间/日期之间进行过滤,那么awk
可能会有所帮助:
awk 'BEGIN {FS=":| +"} {current = mktime("2014 "c($1)" "$2" "$3" "$4" "$5); if (current >= mktime ("2014 12 04 14 30 0") && current <= mktime("2014 12 05 14 29 59")) {print $0 }} function c(s){return(sprintf("%02d\n",(match("JanFebMarAprMayJunJulAugSepOctNovDec",$1)+2)/3)) }' filename
所选时间/日期的格式为 YYYY MM DD HH MM SS。您还会注意到,年份是硬编码的,因为您的日志不包含年份 - 我假设是今年。
上面的一句话,但格式更好,并带有注释:
#!/usr/bin/awk -f
BEGIN {
# Split line into fields using colon or spaces
FS=":| +"
}
{
# Generate the timestamp of the current line from the first 5 fields.
# Use the function c(), defined below, to convert 3 letter months to numerical
current = mktime("2014 "c($1)" "$2" "$3" "$4" "$5);
# If the timestamp of the current line is between two specified
# timestamps then print the whole line
if (current >= mktime ("2014 12 08 15 0 0") && current <= mktime("2014 12 08 16 05 00"))
{print $0 }
}
function c(s) {
# Function to convert three letter month to numerical
# If s == Jan then returns 1. If s == Aug, returns 8
return(sprintf("%02d\n",(match("JanFebMarAprMayJunJulAugSepOctNovDec",$1)+2)/3))
}
答案2
一种解决方案,将日期转换为纪元:
while read month dm hour rest; do
d=$(date -d"$month $dm $hour" "+%m%d%H%M%S")
echo "$d $rest"
done < file | awk '$1 < 1204143737' # print all lines before this date