LINUX.ORG.RU

Удалить строку если следующая начинается не с пробела.


0

1

В результате работы некого скрипта, получаю строки, часть из которых ненужны. В данном примере нужно удалить интерфейсы, в которых ничего не меняется. Те нужно удалить строку если следующая начинается с «interface» (или если следующая начинается не с пробела). Например (удалить нужно помеченые звездочкой):

interface GigabitEthernet0/2.117*
interface GigabitEthernet0/2.118*
interface GigabitEthernet0/2.119*
interface GigabitEthernet0/2.120*
interface GigabitEthernet0/2.121*
interface GigabitEthernet0/2.122*
interface GigabitEthernet0/2.124
 ip dhcp relay information option subscriber-id USER1
interface GigabitEthernet0/2.125*
interface GigabitEthernet0/2.126*
interface GigabitEthernet0/2.127*
interface GigabitEthernet0/2.128*
interface GigabitEthernet0/2.800*
interface GigabitEthernet0/2.802*
interface GigabitEthernet0/2.803*
interface GigabitEthernet0/2.804
 ip dhcp relay information option subscriber-id USER10

Не могу осилить на sed\awk (хотя понимаю что нужно взять текст как строку и тогда /(interface[^\n]*?)\n(interface[^\n]*?)\n/\2/ прогнав раз 10 получить результат). Что то очень близкое нашел тут, но

sed '/^$/{:a N; /[^\n]/{s,^\n\+,\n,; b}; b a}'
повергает меня в шок.


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

bvn13 ★★★★★
()

awk

BEGIN               { m = "^interface"       }
$0 ~ m              { prev = $0; s = 1; next }
$0 !~ m && prev ~ m { if (s) {print prev; s=0}; print }
yoghurt ★★★★★
()
user@host:~$ cat log
interface GigabitEthernet0/2.117*
interface GigabitEthernet0/2.118*
interface GigabitEthernet0/2.119*
interface GigabitEthernet0/2.120*
interface GigabitEthernet0/2.121*
interface GigabitEthernet0/2.122*
interface GigabitEthernet0/2.124
 ip dhcp relay information option subscriber-id USER1
interface GigabitEthernet0/2.125*
interface GigabitEthernet0/2.126*
interface GigabitEthernet0/2.127*
interface GigabitEthernet0/2.128*
interface GigabitEthernet0/2.800*
interface GigabitEthernet0/2.802*
interface GigabitEthernet0/2.803*
interface GigabitEthernet0/2.804
 ip dhcp relay information option subscriber-id USER10
user@host:~$ grep -B 1 "^\ " log | sed '/--/d'
interface GigabitEthernet0/2.124
 ip dhcp relay information option subscriber-id USER1
interface GigabitEthernet0/2.804
 ip dhcp relay information option subscriber-id USER10
sT331h0rs3 ★★★★★
()
Последнее исправление: sT331h0rs3 (всего исправлений: 1)

Если через sed, то вот:

sed -n -e '/^\ /{x;1!p;g;p}' -e h -i log
user@host:~$ cat log
interface GigabitEthernet0/2.117*
interface GigabitEthernet0/2.118*
interface GigabitEthernet0/2.119*
interface GigabitEthernet0/2.120*
interface GigabitEthernet0/2.121*
interface GigabitEthernet0/2.122*
interface GigabitEthernet0/2.124
 ip dhcp relay information option subscriber-id USER1
interface GigabitEthernet0/2.125*
interface GigabitEthernet0/2.126*
interface GigabitEthernet0/2.127*
interface GigabitEthernet0/2.128*
interface GigabitEthernet0/2.800*
interface GigabitEthernet0/2.802*
interface GigabitEthernet0/2.803*
interface GigabitEthernet0/2.804
 ip dhcp relay information option subscriber-id USER10
user@host:~$ sed -n -e '/^\ /{x;1!p;g;p}' -e h -i log
user@host:~$ cat log
interface GigabitEthernet0/2.124
 ip dhcp relay information option subscriber-id USER1
interface GigabitEthernet0/2.804
 ip dhcp relay information option subscriber-id USER10

sT331h0rs3 ★★★★★
()

повергает меня в шок

Привыкай. Но вообще если не хочешь каждый раз вертеться в гробу, когда кто-то будет пытаться понять, что делает эта конструкция - напиши, как уже советовали, простым и понятным перлом. С комментариями.

Deleted
()

sed/awk не знаю, вот тебе однострочник на Perl:

perl -e '$file = "your_file"; open INPUT, "<$file"; $_ = join ("", <INPUT>); close INPUT; s/(?<=\n(?!\ )).*\n(?=interface)//g; s/.*\n//; open OUTPUT, ">$file"; print OUTPUT $_; close OUTPUT'
your_file нужно заменить на имя своего файла, разумеется.

anonymous
()
awk '/^ / || !/^interface/ {print prev; print}; {prev=$0}'
sdio ★★★★★
()
Ответ на: комментарий от sdio

Да, упустил что ему нужна ещё и предыдущая. Но тут, кстати, стоит уточнить а что ему на самом деле надо. У него только такие последовательности строк или ему может иметь смысл сокращать повторяющиеся блоки до одной строки?

sin_a ★★★★★
()
Ответ на: комментарий от sin_a

задача примитивная и неинтересная... еще и ТС нормально описать не может

sdio ★★★★★
()
Ответ на: комментарий от sT331h0rs3

Спасибо. Работают все варианты. Подвела привычка гуглить маны. многих параметров нет, в отличии от оригинального man, например (тот же -B1 у grep).

Не понял только вот это
sed -n -e '/^\ /{x;1!p;g;p}' -e h -i log
-n печатает только совпадения.
-e '/^\ / - тут понятно. находит строку с пробелом.

Но дальше скрипт.. (не пойму что такое pattern space и hold space)
x меняет текующую строку и паттерн поиска (как я понял)... что именно это сделает? от куда тут берется предыдущая строка?
1!p не печатать первую строку.. разве там не всего 1 строка?
g - вданном случае обьединяет найденую строку и патерн поиска

-e h тут как я понял добавить полученый предыдущим скриптом текст «int...\n ip...» к тому что в результате выйдет на stdout (в нашем случае в файл -i log)

DeeZ
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.