У меня есть следующий код, который удалит строки с шаблоном banana
и 2 строки после него:
sed '/banana/I,+2 d' file
Все идет нормально! Но мне нужно, чтобы он убрал 2 строки раньше banana
, но я не могу получить его со знаком «минус» или чем-то еще (похоже на то, что grep -v -B2 banana file
должно делать, но не делает):
teresaejunior@localhost ~ > LC_ALL=C sed '-2,/banana/I d' file
sed: invalid option -- '2'
teresaejunior@localhost ~ > LC_ALL=C sed '/banana/I,-2 d' file
sed: -e expression #1, char 16: unexpected `,'
teresaejunior@localhost ~ > LC_ALL=C sed '/banana/I,2- d' file
sed: -e expression #1, char 17: unknown command: `-'
shell-script
text-processing
sed
awk
Тереза и Джуниор
источник
источник
awk '{l[m=NR]=$0}/banana/{for(i=NR-2;i<=NR;i++)delete l[i]}END{for(i=1;i<=m;i++)if(i in l)print l[i]}'
. Это неэффективно, так что это всего лишь подсказка, а не решение.tac file | sed ... | tac
. : Psed '/banana/,+2d' file
это также будет работатьawk 'tolower($0)~/bandana/{print prev[!idx];print prev[idx]} {idx=!idx;prev[idx]=$0}' filein
как это комментарий, а не ответ (уже есть другие ответы), я не буду вдаваться в подробности, но суть в том, что у вас всегда есть предыдущие две записей в пред [0] и пред [1], «свежайшая» в зависимости от того, какой итерации , но всегдаprev[idx]
, поэтому при печати, печати в!idx
томidx
порядки. Независимо, чередуйтеidx
и вставьте текущую запись вprev[idx]
.Ответы:
Sed не возвращается: как только он обработал строку, он готов. Так что «найти строку и напечатать предыдущие N строк» не будет работать как есть, в отличие от «найти строку и напечатать следующие N строк», на которую легко перейти.
Если файл не слишком длинный, так как вы, кажется, в порядке с расширениями GNU, вы можете использовать,
tac
чтобы перевернуть строки файла.Другим углом атаки является сохранение скользящего окна в таком инструменте, как awk. Адаптация от Есть ли альтернатива переключателям -A -B -C grep (чтобы напечатать несколько строк до и после)? (предупреждение: минимально проверено):
Использование:
/path/to/script -v pattern='banana' -v before=2
источник
sed
Можно также выполнять скользящие окна, но полученный скрипт обычно настолько нечитаем, что его проще использоватьawk
.awk
Сценарий не совсем правильный; как-он печатает пустые строки и пропускает последние строки. Это, кажется, исправляет это, но это не может быть идеальным или правильным само по себе:if (NR-before in h) { print...; delete...; }
... и вEND
разделе:for (i in h) print h[i]
... Кроме того, сценарий awk печатает соответствующую строку, ноtac/sec
версия не делает; но вопрос немного двусмысленен по этому поводу. «Оригинальный» скрипт awk, на который вы предоставили ссылку, работает нормально… Мне это нравится… Я не уверен, как вышеупомянутый «мод» влияет на печать после линии ...Это довольно легко с ex или vim -e
Выражение гласит: для каждой строки, содержащей банан в диапазоне от текущей строки -2 до текущей строки, удалите.
Круто то, что диапазон может также содержать поиск в прямом и обратном направлении, например, при этом будут удалены все разделы файла, начиная со строки, содержащей яблоко, и заканчивая строкой, содержащей оранжевый и содержащей строку с бананом:
источник
Использование «скользящего окна» в
perl
:источник
Вы можете сделать это довольно просто с помощью
sed
:Я не знаю, почему кто-то сказал бы иначе, но чтобы найти строку и напечатать предыдущие строки,
sed
включается встроенныйP
примитив rint, который записывает только до первого\n
символа ewline в пространстве образца. ДополнительныйD
элементарный элемент удаляет тот же сегмент пространства шаблонов перед рекурсивной переработкой сценария с тем, что осталось. И чтобы округлить его, есть примитив для добавленияN
строки ввода ext в пространство образца после вставленного\n
символа ewline.Так что одна строка
sed
должна быть всем, что вам нужно. Вы просто заменяетеmatch
на то, что у вас есть регулярное выражение, и вы золотой. Это должно быть очень быстрое решение.Также обратите внимание, что он будет правильно считать
match
сразу предшествующий другойmatch
как триггер для тихого вывода для предыдущих двух строк, а также для его печати:Чтобы он работал на произвольном количестве строк, все, что вам нужно сделать, это получить преимущество.
Так:
... удаляет 5 строк, предшествующих любому совпадению.
источник
Использование
man 1 ed
:источник