2010-10-06 86 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