コマンドラインを使用した日付による大規模データセットのフィルタリング

コマンドラインを使用した日付による大規模データセットのフィルタリング

タブで区切られた値が行に格納されている巨大なデータセットがあります。例示的な行は次のとおりです。

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))
}

おすすめ記事