Как вставить строки после второго шаблона с помощью команды linux sed - PullRequest
0 голосов
/ 10 января 2019

Я хочу вставить этот блок:

host client3 {
    hardware ethernet c0:03:03:bc:30:fa;
}

после этого блока:

subnet 11.10.0.0 netmask 255.255.255.0 {
    range 11.10.1.2 11.10.1.254;
        group {
            filename "10M-5M-OKS2016NOV.cm";

Строка: filename "10M-5M-OKS2016NOV.cm"; появляется несколько раз в файле. Но только один раз внутри subnet 11.10.0.0 netmask 255.255.255.0 {

До сих пор я могу печатать блок подсети до «имени файла»:

sed -n -e :a -e '/subnet 11\.10\.0\.0 netmask 255\.255\.255\.0/,/}/{/filename "10M-5M-OKS2016NOV\.cm";/!{$!{N;ba};};p;}' dhcpd.conf

но когда я пытаюсь:

sed -n -e :a -e '/subnet 11\.10\.0\.0 netmask 255\.255\.255\.0/,/}/{/filename "10M-5M-OKS2016NOV\.cm";/!{$!{N;ba};};a\ \thost client3     {\n\thardware ethernet c0:03:03:bc:30:fa;\n\t}\n;}' dhcpd.conf

Я получаю:

sed: -e выражение # 1, символ 0: не найдено `{'

subnet 10.10.0.0 netmask 255.255.255.0 {
    range 10.10.0.2 10.10.0.254;
    group {
        filename "10M-5M-OKS2016NOV.cm";
        host client1 {
            hardware ethernet a0:b4:3d:bc:df:fa;
            }
        host client2 {
            hardware ethernet 90:6e:bb:ba:cd:d4;
            }
    }
}
subnet 11.10.0.0 netmask 255.255.255.0 {
    range 11.10.1.2 11.10.1.254;
    group {
        filename "10M-5M-OKS2016NOV.cm";
        host client1 {
            hardware ethernet c0:14:e3:bc:df:fa;
            }
        host client2 {
            hardware ethernet 90:6e:fb:ba:3d:04;
            }
    }
}
subnet 12.10.0.0 netmask 255.255.255.0 {
    range 12.10.2.2 12.10.2.254;
    group {
        filename "10M-5M-OKS2016NOV.cm";
        host client1 {
            hardware ethernet c0:a4:3d:bc:df:fa;
            }
        host client2 {
            hardware ethernet 90:6e:bb:ca:3d:04;
            }
    }
}

Ответы [ 3 ]

0 голосов
/ 11 января 2019

Пожалуйста, попробуйте что-то вроде:

#!/bin/bash

# define newline and tab characters for replacement
NL=$'\n'
NL="\\$NL"
TAB=$'\t'
TAB="\\$TAB"

sed '
:l
N
$!b l
# first of all slurp all lines in the pattern space
# and perform the replacement over the lines
s/subnet 11\.10\.0\.0 netmask 255\.255\.255\.0[^}]*filename "10M-5M-OKS2016NOV\.cm";/&'"$NL$TAB"'host client3 {'"$NL$TAB$TAB"'hardware ethernet c0:03:03:bc:30:fa;'"$NL$TAB"'}/g
' dhcpd.conf

Это дает следующий вывод, используя опубликованные строки как dhcpd.conf,

subnet 10.10.0.0 netmask 255.255.255.0 {
    range 10.10.0.2 10.10.0.254;
    group {
        filename "10M-5M-OKS2016NOV.cm";
        host client1 {
            hardware ethernet a0:b4:3d:bc:df:fa;
            }
        host client2 {
            hardware ethernet 90:6e:bb:ba:cd:d4;
            }
    }
}
subnet 11.10.0.0 netmask 255.255.255.0 {
    range 11.10.1.2 11.10.1.254;
    group {
        filename "10M-5M-OKS2016NOV.cm";
        host client3 {
                hardware ethernet c0:03:03:bc:30:fa;
        }
        host client1 {
            hardware ethernet c0:14:e3:bc:df:fa;
            }
        host client2 {
            hardware ethernet 90:6e:fb:ba:3d:04;
            }
    }
}
subnet 12.10.0.0 netmask 255.255.255.0 {
    range 12.10.2.2 12.10.2.254;
    group {
        filename "10M-5M-OKS2016NOV.cm";
        host client1 {
            hardware ethernet c0:a4:3d:bc:df:fa;
            }
        host client2 {
            hardware ethernet 90:6e:bb:ca:3d:04;
            }
    }
}
  • Изначально он сначала отбрасывает все строки, чтобы эффективно обрабатывать несколько строк.
  • Предполагается, что правильная фигурная скобка } не отображается в целевом блоке поиска. достичь кратчайшего совпадения в регулярном выражении.

Надеюсь, это поможет.

0 голосов
/ 11 января 2019

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

sed '/subnet 11\.10\.0\.0 netmask 255\.255\.255\.0/{:a;n;/filename "10M-5M-OKS2016NOV\.cm";/!ba;p;s/\S.*/host client3 {/p;s//    hardware ethernet c0:03:03:bc:30:fa;/p;s//}/}' file

Находит первую строку, содержащую subnet 11.10.0.0 netmask 255.255.255.0, а затем продолжает чтение до строки, содержащей filename "10M-5M-OKS2016NOV.cm";. После печати этой строки она использует эту строку в качестве шаблона для форматирования требуемой детализации.

Другое решение с использованием предварительно сформированного файла вставки:

cat <<\! | sed '/subnet 11\.10\.0\.0 netmask 255\.255\.255\.0/!b;:a;n;/filename "10M-5M-OKS2016NOV\.cm";/!ba;r /dev/stdin' file
        host client3 {
            hardware ethernet c0:03:03:bc:30:fa;
            }
!
0 голосов
/ 10 января 2019

sed отлично подходит для потокового редактора, что означает многократную обработку одних и тех же действий. Здесь вы просто хотите вставить один раз блок текста. Это было бы намного проще (более читаемым и поддерживаемым) с ed:

ed dhcpd.conf <<EOF
/subnet 11.10.0.0/
/filename/
a
        host client3 {
            hardware ethernet c0:03:03:bc:30:fa;
            }
.
w
q
EOF

Осторожно: редактор - это файл редактор. Это означает, что файл dhcpd.conf будет изменен вышеуказанным сценарием. Убедитесь, что у вас есть резервная копия, если что-то пойдет не так ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...