2010-10-06 82 views
16

我想在文件中的匹配行之前和之後過濾出幾行。帶上下文的grep逆向搜索

這將刪除我不想行:

$ grep -v "line that i don't want" 

,這將之前打印的2線和行之後,我不想:

$ grep -C 2 "line that i don't want" 

但當我把它們合併在一起時,它不會過濾掉我不想要的行前後兩行:

# does not remove 2 lines before and after the line I don't want: 
$ grep -v -C 2 "line that i don't want" 

我如何過濾出不是我不想要的線,還有它之前和之後的線?我猜sed會更好...

編輯:我知道這可以在幾行awk/Perl/Python/Ruby /等,但我想知道是否有一個簡潔的單線我可以從命令行運行。

+1

http://superuser.com – 2010-10-06 15:31:14

+0

是否有原因? – aaronstacy 2010-10-06 15:44:06

回答

4

試試這個:

sed 'h;:b;$b;N;N;/PATTERN/{N;d};$b;P;D' inputfile 

你可以改變模式之前N命令的數量影響行刪除的數目。

您可以以編程方式構建包含N命令的數量的字符串:

C=2 # corresponds to grep -C 
N=N 
for ((i = 0; i < C - 1; i++)); do N=$N";N"; done 
sed "h;:b;\$b;$N;/PATTERN/{N;d};\$b;P;D" inputfile 
+1

不,你的意思是'grep'就是不能這樣做?!有原因嗎?這對我來說是違反直覺的 – n611x007 2012-07-06 15:59:32

+0

@naxa:當「-C」和「-v」一起使用時,「-C」包含排除的行,而不排除其他行。試試這個:'printf'%s \ n'{1..36} | grep --color -C 2 -v'^ 2'',你會看到包含20,21,28和29,而不是18,19,30和31被排除。順便說一下''-C'選項沒有被POSIX指定。 – 2012-07-06 16:22:35

+1

啊我明白了。非常感謝您的關注和現在的色彩!我已經嘗試過-A和-B,但他們的工作都一樣-C。現在,我知道我錯過了尋找的東西,他們似乎也是'非posix'。 – n611x007 2012-07-06 18:32:12

1
awk 'BEGIN{n=2}{a[++i]=$0} 
/dont/{ 
    for(j=1;j<=i-(n+1);j++)print a[j]; 
    for(o=1;o<=n;o++)getline; 
    delete a} 
END{for(i in a)print a[i]} ' file 
+0

我知道你可能已經知道這一點,因爲你比我有更多的XP,但是你可能想要添加更多的解釋,而不僅僅是代碼段,可以解決OP要求提供grep解決方案的事實,同時提供您的其他非常有效且非常有用的AWK解決方案。謝謝! – 2014-11-12 17:41:10

+0

@DermotCanniffe,大聲笑接受的答案是更加令人費解的使用sed。 – ghostdog74 2014-11-13 01:50:00

+0

確實如此。儘管我喜歡sed,但我認爲awk程序更容易解釋。 :) – 2014-11-13 10:37:27

2

如果行都是唯一的,你可以用grep要刪除到一個文件,然後使用該文件來刪除線從原來的線,例如

grep -C 2 "line I don't want" <A.txt> B.txt 
grep -f B.txt A.txt 
0

我認爲@ fxm27有一個很好的bash-y答案。

我想補充一點,如果您事先知道後續行的模式,可以使用egrep另外解決這個問題。

command | egrep -v "words|from|lines|you|dont|want" 

這將做一個「包容性OR」,這意味着該那些任何匹配線將被排除在外。

0

我用兩個順序的grep解決了它,實際上。這對我來說似乎更直接。

grep -C "match" yourfile | grep -v -f - yourfile