2017-07-19 85 views
0

我非常難過。我正在尋找(由find -ing所需的開始日期)和管道多行看起來像這樣的多個文件到grep這樣我就可以提取線組使用此命令:試圖匹配與grep相同的行上的多個模式

find logdir/ -type f -regextype sed -regex ".*2016-06-22.*" | while read fname 
do 
    zgrep -a -P -B9 ".*COOKTHE.*slave.*" $fname 
done 

這樣我就可以輸出組該行:

2017-05-10 12:14:54 DEBUG[dispatcher-1533] something.else.was.here.Pia - http://server:9999/cookout/123123123123/entry c7aab5a3-0dab-4ce1-b188-b5370007c53c request: 
HEADERS: 
Host: server:9999 
Accept: */* 
User-Agent: snakey-requests/2.12.3 
Accept-Encoding: gzip, deflate 
Connection: keep-alive 
Timeout-Access: <function1> 
CONTENT: 
    {"operation": "COOKTHE", "reason": "sucker verified", "username": "slave"} 

我試圖從第一行匹配提取,整個字符串日期模式(2017-05-10 12:14:54)數字模式123123123123和最後一行,整條生產線相匹配。 ({"operation": "COOKTHE", "reason": "sucker verified", "username": "slave"}

如何使用grep,sed或awk提取這些文件?

回答

0

對當前輸入的awk解決方案:

awk 'NR==1{ sub(/http:\/\/[^\/]+\/[^\/]+\//,"",$6); 
    print $1,$2,substr($6,1,index($6,"/")-1)}END{ print $0 }' input 

輸出:

2017-05-10 12:14:54 123123123123 
    {"operation": "COOKTHE", "reason": "sucker verified", "username": "slave"} 
+0

是的,也錯了。我認爲OP希望從第一場比賽到最後一場比賽(以及兩隊之間的比賽)中的所有內容。從Q. – Alfe

+0

中的'-B9'得到的結果是,我實際上在第一行尋找匹配,並抓取整個最後一行。抱歉的誤解。 – Sina

+0

我也可以將查找的結果傳給這個awk命令?我試圖和結果是在兩行 – Sina

0
… | while read fname 
do 
    zcat "$fname" | tr '\n' '\f' | 
    grep -o -P '\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d.*?COOKTHE[^}]*\}' | 
     tr '\f' '\n' 
done 

如果輸入已經包含換頁字符(\f),你可以使用任何其他字符不應該出現在輸入中。

+0

當我運行這個時,我得到了很多'grep:超過PCRE的回溯極限'而沒有其他任何產生。 – Sina

+0

然後你的輸入對於使用這個技巧來說太大了: -/ – Alfe

+0

如果你在其他地方沒有'}',你可以通過插入'|'來解決這個問題。 sed's/\} \ f /} \ n/g''。這會將長的單行輸入拆分爲大括號後的大塊,並可能避免「grep」過程的重載。 – Alfe

1

首先,讓我們簡化您的初始查詢。我不認爲你需要一個正則表達式。 globbing更簡單,更快,更清晰。同樣,你不需要grep的-P選項,因爲你沒有使用PCRE。這也減緩了事情的發展。

find logdir/ -type f -name '*2016-06-22*' | while read fname 
do 
    zgrep -a -B9 '"COOKTHE".*"slave"' "$fname" 
done | grep -e ^20 -e '{' 

重新創建您的原始邏輯,但應該運行得更快一點。它還添加了一個過濾器來顯示你所要求的兩行。不過,我擔心-B9不是一個好的解決方案,因爲可能有數量可變的標題要跟蹤。最後的過濾器也很簡單,只是爲了快速。

下面是一個更完整的解決方案:

find logdir/ -type f -name '*2016-06-22*' | while read fname 
do 
    zcat "$fname" | awk ' 
    /^20/ && $6 ~ /^http/ { 
     split($6, url, "/")   # split the URL by slashes 
     stamp = $1 " " $2 " " url[5] # "2017-05-10 12:14:54 123123123123" 
    } 
    /{.*"COOKTHE".*"slave"/ { print stamp; print } 
    ' 
done 

這節省了日期,時間,URL在stamp變量並打印第5段,只有當你有在JSON線匹配。我修改了你的正則表達式來包含一個{來表示JSON的開始以及引號來改進你的匹配,但是你可以把它改成任何你喜歡的。這個正則表達式不需要前導或尾隨.*

AWK連接相鄰的項目,因此$1 " " $2 " " url[5]僅表示第一列,空格,第二列,另一空格的值,然後是URL的第五項(注意「http:」後面的空項目)。

這不會告訴你哪個文件的匹配文本來自(與grep -H比較)。要做到這一點,你想:

zcat "$fname" | awk -v fname="$fname:" ' 
    # … (see above) 
    /{.*"COOKTHE".*"slave"/ { print fname stamp; print fname $0 } 
    ' 

如果你正在尋找的JSON字符串被放置一致並且間隔,可以轉而做出最終條款$2 ~ /"COOKTHE"/ && $NF ~ /"slave"/這將提高awk的速度(實際上,它的能力失效更快)在更長的線上。

+0

發情。非常感謝! – Sina