タブで区切られた値が行に格納されている巨大なデータセットがあります。例示的な行は次のとおりです。
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
指定した時間がすべてログにない場合は機能しません。
ログにないランダムな2時間/日付の間をフィルタリングするには、次のことが役立ち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