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


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

06.10.2010 07:23:58 Просмотров 112 Источник

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

Это уберет линию, которую я не хочу:

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

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

$ 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будет лучше для этого...

Edit: я знаю, что это можно сделать в нескольких строках awk/Perl/Python/Ruby/etc, но я хочу знать, есть ли краткий однострочный файл, который я мог бы запустить из командной строки.

У вопроса есть решение - Посмотреть?

Ответы - grep инвертировать поиск с контекстом / grep invert search with context

ghostdog74

06.10.2010 07:41:53

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
https://stackoverflow.com/questions/3874112/grep-invert-search-with-context/3874284#comment42339916_3874284
Я знаю, что вы, вероятно, уже знаете это, так как у вас гораздо больше XP, чем у меня, но вы можете добавить немного больше объяснений, чем просто сегмент кода, возможно, обращаясь к тому факту, что OP попросил решение grep, предлагая в остальном очень правильное и чрезвычайно полезное решение AWK. Спасибо!
https://stackoverflow.com/questions/3874112/grep-invert-search-with-context/3874284#comment42352683_3874284
@DermotCanniffe, lol принятый ответ еще более запутан, используя sed.
https://stackoverflow.com/questions/3874112/grep-invert-search-with-context/3874284#comment42363946_3874284
Совершенно верно. Как бы я ни любил sed, я думаю, что процедуры awk гораздо проще объяснить. :)
Является ответом!
Paused until further notice.

06.10.2010 08:11:03

Попробуйте это сделать:

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
https://stackoverflow.com/questions/3874112/grep-invert-search-with-context/3874591#comment14973748_3874591
нет, ты хочешь grepпросто не может этого сделать?! есть ли на то причина? для меня это противоречит здравому смыслу.
https://stackoverflow.com/questions/3874112/grep-invert-search-with-context/3874591#comment14974306_3874591
@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 не указана.
https://stackoverflow.com/questions/3874112/grep-invert-search-with-context/3874591#comment14977341_3874591
а, понятно. спасибо Вам большое за вашу заботу и хороший пример теперь в цвете! Я пробовал с -A и-B, но они работают одинаково-C. Они также кажутся "непозиционными" теперь, когда я знаю, что я пропустил, чтобы искать.
https://stackoverflow.com/questions/3874112/grep-invert-search-with-context/3874591#comment56323097_3874591
Мне очень трудно понять, что ваш однострочный sed делает команда за командой, даже с помощью man-страниц. Я, вероятно, рассмотрю его позже, но если это не слишком сложно, не могли бы вы его сломать? Я думаю, что это пойдет на пользу качеству ответа.
Emery Lapinski

18.12.2013 10:34:22

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

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

12.06.2015 04:42:38

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

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

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

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

LinuxBlanket

05.09.2016 02:21:05

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

grep -C "match" yourfile | grep -v -f - yourfile
https://stackoverflow.com/questions/3874112/grep-invert-search-with-context/39329503#comment105657926_39329503
Это решение не всегда работает; подробности см. в другом ответе .
Ben Winding

13.09.2019 06:43:56

Решение 2019 года

Это простое решение, найденное в другом месте:

grep --invert-match "test*"

Выбирает все не соответствующие "тест*". Супер полезно и легко запоминается!

(Редактировать)

Это не полностью отвечает на исходный вопрос и возвращает весь набор строк, не совпадающих.

https://stackoverflow.com/questions/3874112/grep-invert-search-with-context/57917028#comment105004047_57917028
Это решение не удаляет следующие и последующие строки сопоставления шаблонов.
Помочь в развитии проекта:
Закрыть X