2010-05-15 54 views
2

我正在寫一個loganalysis應用程序,並希望在兩個特定日期之間獲取apache日誌記錄。假定一個日期是這樣形成的:22/Dec/2009:00:19(日/月/年:小時:分鐘)AWK:比較不使用正則表達式的Apache日期

目前,我正在使用正則表達式來替換月份名稱值,刪除分隔符,所以上述日期轉換爲:221220090019作出一個日期比較微不足道......但..

在大型文件的每個記錄上運行一個正則表達式,例如一個包含四分之一百萬記錄,是非常昂貴..是否有任何其他方法不涉及正則表達式替換?

在此先感謝

編輯:這裏是幹什麼的皈依/比較

function dateInRange(t, from, to) { 
    sub(/[[]/, "", t); 
    split(t, a, "[/:]"); 
    match("JanFebMarAprMayJunJulAugSepOctNovDec", a[2]); 
    a[2] = sprintf("%02d", (RSTART + 2)/3); 
    s = a[3] a[2] a[1] a[4] a[5]; 

    return s >= from && s <= to; 
} 

「從」和「到」是在上述格式的時間間隔,而「T」的功能原始的apache日誌日期/時間字段(例如[22/Dec/2009:00:19:36)

+0

也許除了你所要求的,但爲什麼當ISO 8601,即「200912220019」有很多好處時,你想要「221220090019」呢? http://en.wikipedia.org/wiki/ISO_8601 – hlovdal 2010-05-15 20:57:42

+0

沒有想過它真的......那些與易用性比較/性能有關的好處?大部分記錄屬於同一年,同一個小時內的同一年,同一個月,同一天(有時),所以也許是? – smallmeans 2010-05-15 21:18:07

+1

就你而言,最重要的好處是用ISO 8601時間順序和字母順序變得相同。它使年齡排序超級平凡。也許那不是你現在需要的東西,而是爲我們自己一個忙,並且開始使用8601做一切事情,除非你有一個很好的理由不去做。其他好處也列在http://www.cl.cam.ac.uk/~mgk25/iso-time.html。 – hlovdal 2010-05-15 22:39:15

回答

0

我曾經有過涉及正則表達式的非常慢的AWK程序的問題。當我將整個程序翻譯成Perl時,它以更快的速度運行。我想這是因爲GNU AWK每次解釋表達式都會編譯一個正則表達式,其中perl只是編譯一次表達式。

+0

借調。 Awk非常有趣,但Perl速度更快。爲了分析日誌文件,可以考慮用於此目的的任何特殊用途和*快速*工具,如Analog。 – johntellsall 2010-05-15 23:17:06

+0

確實,Perl速度更快,但我選擇AWK是因爲方便:它比太陽還年長,並且已經與每個* nix一起發貨,所以我可以安全地假定它已安裝。 Perl的;不太確定。 如果我正在發佈一個應用程序,那麼我將不得不使用最低分母。此外,在處理文本數據時,Perl與AWK在簡潔性和簡潔性方面並不匹配(請注意,我的Perl的權限是有限的) – smallmeans 2010-05-16 21:48:26

0

那麼,這是一個想法,假設日誌中的記錄按日期排序。

而不是在文件的每一行上運行regexp,並檢查該記錄是否在要求的範圍內,請執行binary search

獲取文件中的總行數。從中間讀一行,並檢查它的日期。如果它大於你的範圍 - 那麼該行之前的任何內容都可以忽略。將剩下的一半分開,然後再從中間檢查一行。等到你找到你的範圍界限爲止。

0

Here is a Python program I wrote要通過基於日期的日誌文件進行二進制搜索。它可以適應您的使用。

它尋找到文件的中間,然後同步到一個換行符,讀取和比較日期,重複進程拆分前一半的過程,這樣做,直到日期匹配(大於或等於),倒帶,使確定之前沒有更多的日期,然後讀取並輸出行,直到所需範圍的結束。速度非常快。

我在作品中有更高級的版本。最終我會完成併發布更新的版本。

0

搓背文件只是爲了識別範圍的聲音對於這樣一個簡單的任務有點重手(二進制搜索是值得考慮的,雖然)

這裏是我的修改功能,這顯然是因爲正則表達式被消除得更快

BEGIN { 
    months["Jan"] = 1 
    months["Feb"] = 2 
    .... 
    months["Dec"] = 12 
} 
function dateInRange(t, from, to) { 
    split(t, a, "[/:]"); 
    m = sprintf("%02d", months[a[2]]); 
    s = a[3] m a[1] a[4] a[5]; 
    ok = s >= from && s <= to; 
    if(!ok && seen == 1){exit;} 
    return ok; 
} 

一個數組被定義並隨後用於索引月份。 它確保這並不繼續檢查記錄一次約會是超出了範圍(可變看到設置在第一場比賽)

謝謝大家對您的輸入的程序。