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

时间:2017-03-03 14:56:43

标签: linux awk sed

我试图添加" dns-nameservers x.x.x.x"特定ethX设备到/ 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 个答案:

答案 0 :(得分: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),但搜索在第二个文件上继续。

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

答案 1 :(得分:3)

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

$ 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地址,或仅匹配环回或您可能想要选择或操作的任何其他内容或您要打印的特定行或基于每个设备的任何其他内容。

答案 2 :(得分:1)

这可能适合你(GNU sed):

auto em1

此后遇到auto个打印行并在下一行INSERT INTO tasks (text, date, parent, projectid) SELECT text, date, parent, 89 FROM tasks WHERE projectid = 23 之前插入所需的字符串。

答案 3 :(得分:1)

$ 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