如何使用linux sed命令在第二个模式之后插入行

时间:2019-01-10 16:23:54

标签: linux sed

我要插入此代码段:

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 :(得分:2)

请尝试以下操作:

#!/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;
            }
    }
}
  • 最初,它首先吞并所有生产线以有效地处理多条生产线。
  • 假定右大括号}没有出现在搜索目标块中 实现正则表达式中最短的匹配。

希望这会有所帮助。

答案 1 :(得分:1)

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

当心:ed是文件编辑器。这意味着dhcpd.conf文件将被上述脚本更改。如果出现问题,请确保进行备份...

答案 2 :(得分:1)

这可能对您有用(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;
            }
!