首页 文章

如何在两个匹配的模式之间但在第二个模式之前插入一条线

提问于
浏览
1

我正在尝试将特定ethX设备的“dns-nameservers x.x.x.x”行添加到/ etc / network / interfaces(这可以更改,它可能是另一个文件的另一行 . )

即将dns-nameservers添加到em1我想使用类似的东西:

sed -i '/^auto em1/,/^auto/ .....' /etc/network/interfaces

目前:

auto lo
iface lo inet loopback
auto em1
iface em1 inet static
address 192.168.2.98
netmask 255.255.255.0
gateway 192.168.2.1
auto eth1
iface eth1 inet static
address 192.168.3.155
netmask 255.255.255.0
dns-nameservers 8.8.8.8

我想要的是:

auto lo
iface lo inet loopback
auto em1
iface em1 inet static
address 192.168.2.98
netmask 255.255.255.0
gateway 192.168.2.1
dns-nameservers x.x.x.x (<- this line inserted)
auto eth1
iface eth1 inet static
address 192.168.3.155
netmask 255.255.255.0
dns-nameservers 8.8.8.8

提前致谢 .

4 回答

  • 3

    awk 来救援!

    $ awk '/^auto em1/       {f=1} 
           /^auto eth1/ && f {print "NEW LINE GOES HERE"; f=0}1' file
    
    auto lo
    iface lo inet loopback
    auto em1
    iface em1 inet static
    address 192.168.2.98
    netmask 255.255.255.0
    gateway 192.168.2.1
    NEW LINE GOES HERE
    auto eth1
    iface eth1 inet static
    address 192.168.3.155
    netmask 255.255.255.0
    dns-nameservers 8.8.8.8
    

    使用示例澄清注释:匹配将在文件之间继续(如果找到多对开始/结束模式,则循环) . 例如

    $ awk '/^3/     {f=1} 
           /^6/ && f{print "HERE"; f=0}1' <(seq 5) <(seq 4 7)
    
    1
    2
    3
    4
    5
    4
    5
    HERE
    6
    7
    

    第一个输入文件没有结束模式(即6),但搜索在第二个文件上继续 .

    如果这不是缩进行为,请澄清问题 .

  • 3
    $ cat program.awk
    /^auto/ && f { print "THE LINE"; f=0 }  # auto and f flag up will trigger printing
    /^auto em1/ { f=1 }                     # auto em1 raises f flag
    1                                       # implicit print
    END{ if(f==1) print "THE LINE" }        # if the "auto em1 block" is the last
    

    修改的测试数据:

    $ cat foo
    auto lo
    iface lo inet loopback
    auto eth1
    iface eth1 inet static
    address 192.168.3.155
    netmask 255.255.255.0
    dns-nameservers 8.8.8.8
    auto em1
    iface em1 inet static
    address 192.168.2.98
    netmask 255.255.255.0
    gateway 192.168.2.1
    

    测试一下:

    $ awk -f program.awk foo
    auto lo
    iface lo inet loopback
    auto eth1
    iface eth1 inet static
    address 192.168.3.155
    netmask 255.255.255.0
    dns-nameservers 8.8.8.8
    auto em1
    iface em1 inet static
    address 192.168.2.98
    netmask 255.255.255.0
    gateway 192.168.2.1
    THE LINE
    

    单行版:

    $ awk '/^auto/ && f { print "THE LINE"; f=0 } /^auto em1/ { f=1 } { print } END{ if(f==1) print "THE LINE" }' foo
    
  • 1

    这可能适合你(GNU sed):

    sed '/^auto em1/!b;:a;$bb;n;/^auto/!ba;:b;idns-nameservers x.x.x.x' file
    

    在此后遇到 auto em1 打印行并在下一行开始 auto 之前插入所需的字符串 .

  • 1

    满足您当前和未来需求的解决方案是将与给定设备关联的每组线路保存为单个记录,然后从函数中打印出来,例如:

    $ awk '/^auto/{prtDev()} {dev = dev $0 ORS} END{prtDev()}
        function prtDev() {printf "%s", dev; dev=""}' file
    auto lo
    iface lo inet loopback
    auto em1
    iface em1 inet static
    address 192.168.2.98
    netmask 255.255.255.0
    gateway 192.168.2.1
    auto eth1
    iface eth1 inet static
    address 192.168.3.155
    netmask 255.255.255.0
    dns-nameservers 8.8.8.8
    

    虽然看起来它只是按原样打印输入文件,但看看它是多么容易,然后调整函数让它在第二个设备的末尾添加一行:

    $ awk '/^auto/{prtDev()} {dev = dev $0 ORS} END{prtDev()}
        function prtDev() {printf "%s", dev; if (cnt++ == 2) print "dns-nameservers x.x.x.x"; dev=""}' file
    auto lo
    iface lo inet loopback
    auto em1
    iface em1 inet static
    address 192.168.2.98
    netmask 255.255.255.0
    gateway 192.168.2.1
    dns-nameservers x.x.x.x
    auto eth1
    iface eth1 inet static
    address 192.168.3.155
    netmask 255.255.255.0
    dns-nameservers 8.8.8.8
    

    或者只打印设备“em1”的记录:

    $ awk '/^auto/{prtDev()} {dev = dev $0 ORS} END{prtDev()}
        function prtDev() {if (dev ~ / em1 /) printf "%s", dev; dev=""}' file
    auto em1
    iface em1 inet static
    address 192.168.2.98
    netmask 255.255.255.0
    gateway 192.168.2.1
    

    或匹配特定的网关IP地址,或仅匹配环回或您可能想要选择或操作的任何其他内容或您要打印的特定行或基于每个设备的任何其他内容 .

相关问题