명령줄을 사용하여 날짜별로 대규모 데이터 세트 필터링

명령줄을 사용하여 날짜별로 대규모 데이터 세트 필터링

탭으로 구분된 값이 행에 저장되어 있는 거대한 데이터 세트가 있습니다. 예시 라인은 다음과 같습니다:

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

관련 정보