Как удалить конкретную строку и строки непосредственно до и после нее?

Я делаю краткое изложение файлов history.log в /var/log/apt. Для этого я хочу удалить строки, содержащие определенный шаблон, а также строку, непосредственно предшествующую, и строку, следующую непосредственно за строкой, содержащей шаблон.

В следующем примере:

 1  Start-Date: 2012-10-18  17:34:12
 2  Commandline: /usr/sbin/synaptic
 3  Install: qpdf:i386 (3.0.2-1)
 4  End-Date: 2012-10-18  17:34:21

 5  Start-Date: 2012-10-20  16:56:26
 6  Commandline: apt-get upgrade
 7  End-Date: 2012-10-20  16:56:39

 8  Start-Date: 2012-10-24  09:15:11
 9  Commandline: apt-get upgrade
10  End-Date: 2012-10-24  09:15:26

11  Start-Date: 2012-10-26  18:40:20
12  Commandline: aptdaemon role='role-install-packages' sender=':1.196'
13  Install: gcolor2:i386 (0.4-2.1ubuntu1)
14  End-Date: 2012-10-26  18:40:31

15  Start-Date: 2012-10-27  07:20:03
16  Commandline: apt-get upgrade
17  End-Date: 2012-10-27  07:20:11

18  Start-Date: 2012-10-29  16:32:33
19  Commandline: /usr/sbin/synaptic
20  Install: policykit-desktop-privileges:i386 (0.12)
21  End-Date: 2012-10-29  16:32:40

Я хочу удалить строки 5, 6 и 7, строки 8, 9 и 10 и строки 15, 16 и 17.

Все, что я могу сделать, это sed -rs ''/apt-get\ upgrade/,+1'd;', который удаляет строку, содержащую apt-get upgrade, и строку, следующую за ней.

2
задан 18 April 2013 в 17:37

2 ответа

Не совсем понятно, насколько вы хотите, но awk, который выполняет эту конкретную задачу, может быть:

awk 'BEGIN{ RS=""; ORS="\n\n"; } !/apt-get upgrade/' /var/log/apt/history.log

вы можете расширить его с помощью большего количества паттернов

awk 'BEGIN{ RS=""; ORS="\n\n"; } !/apt-get upgrade/ && !/apt-get install hello/' /var/log/apt/history.log

Он работает, устанавливая разделитель записей RS (который по умолчанию является новой строкой) в пустую строку. Пустой RS обрабатывается специально, чтобы означать, что пустые строки разделяют записи (вместо новых строк).

0
ответ дан 18 April 2013 в 17:37

Хорошо, что-то ужасное, но работа:

pattern="apt-get\ upgrade"
prog="BEGIN {b=0} /$pattern/ {print; b=1; next} {if (b==1) {b=0;next;} else {print;}}"
cat test | awk "$prog" | tac | awk "$prog" |tac | grep -v "$pattern"

Вторая строка создает awk программу, которые удаляют строку после той, где шаблон найден.

Затем эта программа запущена на тестовом файле, вывод инвертируется, прогон программы снова, производится, инвертируется, и строка с шаблоном удалена.

Что-то короче, с тем же подходом:

cat test | sed -e "/$pattern/{n;d}" | tac | sed -e "/$pattern/,+1d" |tac

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

0
ответ дан 18 April 2013 в 17:37

Другие вопросы по тегам:

Похожие вопросы: