2011-05-03 118 views
3

我正在嘗試處理日誌文件,並且需要能夠指定日期範圍。到目前爲止(在任何處理之前),我使用date --date "monday" +%s將日期/時間字符串轉換爲時間戳。在AWK內運行shell命令

現在,我想能夠遍歷文件中的每一行,但檢查日期(以可讀格式)是否在允許的範圍內。要做到這一點,我想這樣做如下:

echo `awk '{if(`date --date "$3 $4 $5 $6 $7" +%s` > $START && `date --date "" +%s` <= $END){/*processing code here*/}}' myfile` 

我甚至不知道如果多數民衆贊成可能的...我已經嘗試了很多的變化,再加上我找不到任何東西可以在線理解/使用。

由於

更新:

MYFILE的實施例是如下。它記錄IP地址和訪問時間:

123.80.114.20  Sun May 01 11:52:28 GMT 2011 
144.124.67.139  Sun May 01 16:11:31 GMT 2011 
178.221.138.12  Mon May 02 08:59:23 GMT 2011 
+2

作爲對date命令進行脫殼的替代方案,可以考慮使用內置的awk函數mktime()來從字符串中解析日期。例如:sec = mktime($ 3「」$ 4「」$ 5「」$ 6「」$ 7「00」);如果($ sec> $ START)... – neillb 2011-05-03 21:14:25

+0

這是一個一次性項目,還是每天要處理兆字節的日誌文件? – shellter 2011-05-03 21:26:04

+0

一次性。它實際上是考試的修訂版,在課堂筆記中找不到關於它的任何內容。在這裏更容易提問,因爲答案往往更好! – Josh 2011-05-03 21:28:36

回答

1

鑑於你必須做的事情,它確實不那麼難,通過轉換爲字符串和比較來完成日期處理要高效得多。

以下是使用關聯數組將月份值轉換爲數字的部分解決方案。然後你依靠%02d格式說明符來確保2位數。如果您真的需要人的可讀性,您可以使用'。'等重新格式化dateTime值,或將冒號留在hr:min:sec中。

YYYYMMDD格式對於這類問題很有幫助,因爲LT,GT,EQ都可以在沒有進一步格式化的情況下工作。

echo "178.221.138.12  Mon May 02 08:59:23 GMT 2011" \ 
| awk 'BEGIN { 
mons["Jan"]=1 ; mons["Feb"]=2; mons["Mar"]=3 
mons["Apr"]=4 ; mons["May"]=5; mons["Jun"]=6 
mons["Jul"]=7 ; mons["Aug"]=8; mons["Sep"]=9 
mons["Oct"]=10 ; mons["Nov"]=11; mons["Dec"]=12 
} 
{ 
    # 178.221.138.12  Mon May 02 08:59:23 GMT 2011 
    printf("dateTime=%04d%02d%02d%02d%02d%02d\n", 
     $NF, mons[$3], $4, substr($5,1,2), substr($5,4,2), substr($5,7,2)) 
} ' -v StartTime=20110105235959 

-v StartTime是如何傳入(和匹配格式)您的starTime值的說明。

我希望這會有所幫助。

+0

是的,這很好地工作!我以前嘗試過數組,但無法正常工作。謝謝 :) – Josh 2011-05-03 21:59:14

0

我不知道你在分析數據的格式,但我知道,你不能單引號內使用反引號。你將不得不使用雙引號。如果嵌套的引用過多,而且令人困惑,那麼您可以事先將date命令的輸出保存到變量中。

1

下面是使用awk的內置mktime()函數的另一種方法。我從來沒有對這個月的解析感到困擾 - 這要歸功於那個部分的庇護所(參見接受的答案)。總是覺得時間在這一點上轉換語言。

#!/bin/bash 
# input format: 
#(1     2 3 4 5  6 7) 
#123.80.114.20  Sun May 01 11:52:28 GMT 2011 

awk -v startTime=1304252691 -v endTime=1306000000 ' 
BEGIN { 
    mons["Jan"]=1 ; mons["Feb"]=2; mons["Mar"]=3 
    mons["Apr"]=4 ; mons["May"]=5; mons["Jun"]=6 
    mons["Jul"]=7 ; mons["Aug"]=8; mons["Sep"]=9 
    mons["Oct"]=10 ; mons["Nov"]=11; mons["Dec"]=12; 
} 
{ 
    hmsSpaced=$5; gsub(":"," ",hmsSpaced); 
    timeInSec=mktime($7" "mons[$3]" "$4" "hmsSpaced); 
    if (timeInSec > startTime && timeInSec <= endTime) print $0 
}' myfile 

(我選擇了例如時間閾值來選擇只有最後兩個日誌行。)

注意,如果mktime()功能是一個有點聰明這整個事情將減少到:

awk -v startTime=1304252691 -v endTime=1306000000 't=mktime($7" "$3" "$4" "$5); if (t > startTime && t <= endTime) print $0}' myfile