Я делаю краткое изложение файлов 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
, и строку, следующую за ней.
Не совсем понятно, насколько вы хотите, но 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
обрабатывается специально, чтобы означать, что пустые строки разделяют записи (вместо новых строк).
Хорошо, что-то ужасное, но работа:
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
Я полагаю, что инвертирование файла обязательно, потому что к моему знанию, обрабатывающий поток наклон инструментов идет назад.