2012-12-19 22 views
1

我知道-A-B-C可以用來顯示圍繞grep關鍵字的上下文。在不同的grep關鍵字上顯示不同的上下文?

我的問題是,如何在不同的關鍵字上顯示不同的上下文?

例如,如何顯示-A 5貓,-B 4狗,和-C 1猴:

egrep -A3 "cat|dog|monkey" <file> 
// this just show 3 after lines for each keyword. 
+0

可能重複的 有一個非常好的解決方案使用sed那裏。 – RaveTheTadpole

回答

1

我不認爲有任何方式與單grep的呼叫這樣做,但你可以通過grep的每個變量運行一次並連接輸出:

var=$(grep -n -A 5 cat file)$'\n'$(grep -n -B 4 dog file)$'\n'$(grep -n -C 1 monkey file) 
var=$(sort -un <(echo "$var")) 

現在echo "$var"將產生相同輸出,就像你從單個命令中得到的那樣,加上行號和上下文指示符(:前綴表示與該模式完全匹配的行,而-前綴表示因爲-A-B和/或-C選項而包含的行) 。

到目前爲止,我包含行號的原因是爲了保持您在一個語句中設法做到這一點的結果順序。如果你喜歡他們,偉大的,但如果沒有,你可以使用下面的線切割出來:

var=$(cut -d: -f2- <(echo "$var") | cut -d- -f2-) 

這使其通過一次切割精確匹配線的前綴,然後再削減上下文匹配'前綴。

漂亮嗎?沒有。但它的工作原理。

+0

+1,但如果匹配行包含「 - 」,並且您不需要變量或回顯,則可能會導致其他故障,所以多次切割將失敗。我認爲這會做到:'$(f =「file」; grep -n -A 5 cat「$ f」; grep -n -B 4 dog「$ f」; grep -n -C 1 monkey「$ f 「)| sort -un | sed -r's/^ [^: - ] + [: - ] //''。我只是引入了「f」來保存多次指定相同的文件名。 –

+0

我認爲剪切是可以的,因爲我指定了'-f2-',它告訴它通過行尾打印字段2。所以即使其餘的包含'-'或':'也應該沒問題。(我在想這個錯誤嗎?),但是否則我同意你的評論,並且像你引入$ f代替重複文件名一樣。 – nullrevolution

+0

'cut -d:|的問題cut -d-'是那些恰好包含其中一個字符的行會重新被截斷。例如,如果你有兩行,例如'7:round-up'和'9-10:30',你想分別打印'round-up'和'10:30',你最終會打印' up'和'30'。 –

1

恐怕grep不會那麼做的。你將不得不使用不同的工具。也許寫你自己的程序。

0

像這樣的事情會做到這一點:

awk ' 
    BEGIN{ ARGV[ARGC++] = ARGV[1] } 

    function prtB(nr) { for (i=FNR-nr; i<FNR;  i++) print a[i] } 
    function prtA(nr) { for (i=FNR+1; i<=FNR+nr; i++) print a[i] } 

    NR==FNR{ a[NR]; next } 

    /cat/ { print; prtA(5) } 
    /dog/ { prtB(4); print } 
    /monkey/ { prtB(1); print; prtA(1) } 

' file 

檢查數學上的功能的迴路。例如,你沒有說出你想如何處理包含猴子和狗的線。

編輯:這裏是將打印出來的最大範圍內周圍的任何比賽,讓你在命令行指定的上下文並不會使用盡可能多的內存上面的便宜歡快的解決方案未經檢驗的解決方案:

awk -v cxts="cat:0:5\ndog:4:0\nmonkey:1:1" ' 
    BEGIN{ 
     ARGV[ARGC++] = ARGV[1] 
     numCxts = split(cxts,cxtsA,RS) 
     for (i=1;i<=numCxts;i++) { 
     regex = cxtsA[i] 
     n = split(regex,rangeA,/:/) 
     sub(/:[^:]+:[^:]+$/,"",regex) 
     endA[regex] = rangeA[n] 
     startA[regex] = rangeA[n-1] 
     regexA[regex] 
     } 
    } 

    NR==FNR{ 
     for (regex in regexA) { 
     if ($0 ~ regex) { 
      start = NR - startA[regex] 
      end = NR + endA[regex] 
      for (i=start; i<=end; i++) { 
       prt[i] 
      } 
     } 
     } 
     next 
    } 

    FNR in prt 

' file 

在cxts變量中將搜索到的模式與RS值無關,默認爲換行符。

相關問題