2016-12-13 3 views
1

У меня есть конфигурационный файл с текстом:СЭД вставить строку перед последней строкой в ​​определенном порядке

*filter 
:INPUT DROP [0:0] 
:FORWARD DROP [0:0] 
:OUTPUT ACCEPT [0:0] 
:sdfilter - [0:0] 
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT 
-A sdfilter -j DROP 
COMMIT 
*nat 
:OUTPUT ACCEPT [0:0] 
:ds - [0:0] 
-A POSTROUTING -o dev -j MASQUERADE 
COMMIT 
*mangle 
:PREROUTING ACCEPT [0:0] 
:POSTROUTING ACCEPT [0:0] 
-A POSTROUTING -o dev -j MASQUERADE 
COMMIT 

и я пытаюсь вставить строку -I FORWARD -m physdev --physdev-in eth2 -j DROP между *filter и первым COMMIT и только перед COMMIT в что модель .so, что в результате вывода выглядит следующим образом:

*filter 
:INPUT DROP [0:0] 
:FORWARD DROP [0:0] 
:OUTPUT ACCEPT [0:0] 
:sdfilter - [0:0] 
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT 
-A sdfilter -j DROP 
-I FORWARD -m physdev --physdev-in eth2 -j DROP 
COMMIT 
*nat 
:OUTPUT ACCEPT [0:0] 
:ds - [0:0] 
-A POSTROUTING -o dev -j MASQUERADE 
COMMIT 
*mangle 
:PREROUTING ACCEPT [0:0] 
:POSTROUTING ACCEPT [0:0] 
-A POSTROUTING -o dev -j MASQUERADE 
COMMIT 

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

sed '/\*filter/,/COMMIT/i\FORWARD -m physdev --physdev-in eth2 -j DROP' file 

Пожалуйста, предложите образец, который я могу вставить только в прошлую («COMMIT») в этом отфильтрованном паттерне?

ответ

0

Использование awk я могу написать,

/^\*filter$/{found++} 
found && /COMMIT/ { 
    print "-I FORWARD -m physdev --physdev-in eth2 -j DROP"; 
    found=0 
} 
1 


Что такое делает?

  • /^\*filter$/{found++} Если текущая строка *filter, increament found один.

  • found && /COMMIT/ Если текущая строка имеет COMMIT и filter не равен нулю,

    • Печатает строку, что нам нужно напечатать и установить found к нулю.
  • 1 Это всегда так, в этом случае awk выполняет задание по умолчанию для печати текущей строки.


Пример

$ awk '/^\*filter$/{found++} found && /COMMIT/{print "-I FORWARD -m physdev --physdev-in eth2 -j DROP"; found=0} 1' file 
*filter 
:INPUT DROP [0:0] 
:FORWARD DROP [0:0] 
:OUTPUT ACCEPT [0:0] 
:sdfilter - [0:0] 
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT 
-A sdfilter -j DROP 
-I FORWARD -m physdev --physdev-in eth2 -j DROP 
COMMIT 
*nat 
:OUTPUT ACCEPT [0:0] 
:ds - [0:0] 
-A POSTROUTING -o dev -j MASQUERADE 
COMMIT 
*filter 
:PREROUTING ACCEPT [0:0] 
:POSTROUTING ACCEPT [0:0] 
-A POSTROUTING -o dev -j MASQUERADE 
-I FORWARD -m physdev --physdev-in eth2 -j DROP 
COMMIT 
+0

Большое спасибо за решение. – namus

0

Здесь речь идет sed ответ:

sed -n -r '/COMMIT/{x; s/(\*filter.*)/\1\n-I FORWARD -m physdev --physdev-in eth2 -j DROP/; p; x;p; b end }; H; b; :end n; p; b end' config_file | sed -e '1d' 

Заменить --inserted text-- с текстом, который будет добавлен перед первым " COMMIT ', plaese.

Объяснение

  • H добавляет текущую строку в буфер
  • b <label> - переходите к
  • : <label> - определение
  • b - с не просто заканчивается на текущую обработку строки
  • n - перейти на следующую строку
  • x - шаблон замены и держать буфер (есть только thoose два в sed)
  • p - печатный рисунок буфер на экране
+0

Большое спасибо за ваше решение Marek .. меня беспокоит только то, что шаблон sed добавляет новую строку в начале файла. Не могли бы вы исправить это. – namus

+0

Теперь это исправлено .. –

0

Это может работать для вас (GNU СЭД):

sed -e '/^\*filter/,/^COMMIT/{/^COMMIT/{i-I FORWARD -m physdev --physdev-in eth2 -j DROP' -e ':a;n;ba}}' file 

Найдите диапазон строк между *filter и COMMIT, затем вставьте нужную строку перед строкой, содержащей COMMIT, и, наконец, напечатайте все следующие строки.

Смежные вопросы