Grep инвертировать поиск с контекстом

Я хочу отфильтровать несколько строк до и после соответствующей строки в файле.

Это приведет к удалению строки, которую я не хочу:

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

И это напечатает две строки до и после строки, которую я не хочу:

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

Но когда я их совмещаю, он не отфильтровывает 2 строки до и после строки, которую я не хочу:

# 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/etc, но я хочу знать, есть ли один лайнер, который можно выполнить из командной строки.

Ответы

Ответ 1

Попробуйте:

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

Ответ 2

Если строки уникальны, вы можете grep строки, которые хотите удалить в файл, а затем использовать этот файл для удаления строк из оригинала, например

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

Ответ 3

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

Ответ 4

Я думаю, что @fxm27 имеет отличный ответ bash -y.

Я бы добавил, что вы могли бы решить этот другой способ, используя egrep, если бы заранее знали шаблоны последующих строк.

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

Это сделает "включительно ИЛИ", что означает, что строка, соответствующая любому из них, будет исключена.

Ответ 5

Я решил это с двумя последовательными grep, на самом деле. Для меня это кажется более простым.

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