2017-02-20 25 views
1

Моего тестового файла test.txt приведен ниже:Удалить диапазон строк из файла с помощью сценария оболочки

destination mailerr { file("/var/log/mail.err" fsync(yes)); }; 
log { source(src); filter(f_mailerr); destination(mailerr); }; 

# 
# and also all in one file: 
# 
destination mail { file("/var/log/mail"); }; 
log { source(src); filter(f_mail); destination(mail); }; 

destination mailwarn { file("/var/log/mail.warn"); }; 
log 
{ 
#source(src); 
filter(f_mailwarn); destination(mailwarn); }; 

Я хочу удалить ниже строк с использованием сценария оболочки

log 
{ 
#source(src); 
filter(f_mailwarn); destination(mailwarn); }; 

этой линии может быть приходит другая структура как

log{ source(src); filter(f_mailwarn); destination(mailwarn); }; 
          (or) 
log 
{ 
source(src); 
filter(f_mailwarn); 
destination(mailwarn); 
}; 
          (or) 
log 
{ source(src); filter(f_mailwarn); destination(mailwarn); }; 
          (or) 
# log { source(src); filter(f_mailwarn); destination(mailwarn); }; 
}; 

Это возможности. Я использую команду sed:

sed '/log/{:a;/destination(mailwarn);.*}/d;N;ba}' test.txt 

Но он удалит всю строку, потому что первая строка его «лог» приходит. Так много «log» приходит в этот файл, поэтому, как удалить конкретные строки, используя сценарий оболочки.

+0

Я думаю, что этот вопрос нуждается в некотором уточнении. Вы просто пытаетесь удалить строки из файла на основе списка строк для удаления, пытаетесь ли вы удалить всю функцию «log», или пытаетесь ли вы сделать что-то еще, что я не понимаю? –

+0

@Jeffrey Cash Я хочу удалить функцию журнала, которая содержит «destination (mailwarn)»; – SSN

ответ

1

Вы можете попробовать это sed:

sed '/^[# ]*log/{:loop; /destination(.*}/d; /}/{n}; N; b loop;}' file 

Объяснение:

  • /^[# ]*log/ - Запускает для обработки блока {} когда regex матчи.
  • /destination(.*}/d - Удаляет пространство для образца, когда regex соответствует. Начинается новый цикл.
  • /}/{n} - Когда он находит }, затем печатает пространство для рисунка и читает следующую строку ввода. . (Для распечатки в нон log...destination() линии
  • N - Это добавляет следующий вход строки шаблона
  • b loop - Это передает управление потоком в loop
+0

Можете ли вы добавить в это немного объяснения? действительно хочу понять это и повысить его :) – Inian

+1

Это, похоже, не работает для меня. Он удаляет все функции 'log', а не только те, у которых есть' destination (mailwarn) ' –

0

С Седом:.

sed '/^#*[[:blank:]]*log/{:a;/};/!{N;ba;s/\n//;};/destination(mailwarn)/d;}' file 
.

Добавляет линии от log до }; в произвольное пространство, Искать в этом файле для destination(mailwarn) и если найдено, то удалите строки.

0

Вот мой несколько явный способ получить работу. Кажется, он работает во всех случаях, которые вы опубликовали, но никоим образом не является универсальным решением этой проблемы.

tr '\n' '\0' < test.txt | sed 's/log[^{}]*{[^}]*destination(mailwarn);[^}]*};//g' | tr '\0' '\n'

Если test.txt содержит нулевые символы, он может не работать должным образом. Эта команда по существу ищет log, а затем { в какой-то момент, затем до } достигнуто destination(mailwarn);, после чего следует }; и удаляет это совпадение, если найдено.

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

1

Если файл не слишком велик, используйте опцию -z обработать весь файл в одном кадре (@SLePort отмечает, что это конкретный вариант GNU)

sed -z 's/log[ \t\n]*{[^}]*destination(mailwarn);[ \t\n]*};//g' test.txt 
  • log начала матча
  • [ \t\n]*{ ноль или более не пространство/вкладка/символы новой строки с последующего {
    • , чтобы избежать ложного соответствия log/mail.warn"); };, если [^{]*{ использовали вместо
  • [^}]* ноль или более не } символы
  • destination(mailwarn); строку, чтобы соответствовать
  • [ \t\n]*}; ноль или более не пространство/Tab/символы новой строки с последующим };
  • согласованный шаблон получает удалены, поскольку строка замены пуста


Похожие с perl

perl -0777 -pe 's/log\s*\{[^}]*destination\(mailwarn\);\s*};//g' test.txt 
+1

Стоит отметить, что' -z' является флагом GNU sed. – SLePort

+2

@SLePort спасибо, добавлено в ответ – Sundeep

+0

Хорошее использование функции GNU 'sed' ++ – anubhava