我有一个包含以下内容的 XML 文件:
<ipaddr>192.168.1.1</ipaddr>
<subnet>24</subnet>
目标是在一个命令中修改<ipaddr>192.168.1.1</ipaddr>
to<ipaddr>192.168.1.125</ipaddr>
和<subnet>24</subnet>
to 。<subnet>25</subnet>
我不想更改文件内的任何其他子网标记。
我遇到的问题是后面有一个换行符</ipaddr>
,前面有两个制表符<subnet>
。
我已经尝试过这个:awk '{gsub (/<ipaddr>192.168.1.1<\/ipaddr>\n<subnet>24<\/subnet>/, "<ipaddr>192.168.1.125<\/ipaddr>\n\t\t<subnet>25<\/subnet>")}' config.xml
但它不起作用。
有人可以指导我正确的方向吗?
答案1
假设您要更改一行上的 IP 和下一行上的子网:
sed -E '/(192.168.1.)1/{s//\1125/; n; s/>24</>25</}' infile
如果 IP 更改但子网未更改,则不会报告任何错误。从你的描述来看这似乎是你想要的。
答案2
这是一个相当不完整的规范。我们要寻找什么?一些通用模式?确切的IP地址和子网?如果是,请尝试
$ sed -r '/(192.168.1.)1/{s//\1125/; N; s/24/25/}' file
<ipaddr>192.168.1.125</ipaddr>
<subnet>25</subnet>
答案3
假设数据是格式良好的 XML 文档,如下所示:
<?xml version="1.0"?>
<root>
<ipaddr>192.168.1.2</ipaddr>
<subnet>24</subnet>
<ipaddr>192.168.1.1</ipaddr>
<subnet>24</subnet>
</root>
以下 XMLStarlet 命令将查找ipaddr
当前值为192.168.1.1
且第一个subnet
同级节点为 24 的节点,并将该ipaddr
节点值更改为192.168.1.125
。然后,它会执行类似的操作,将subnet
节点的值更改为 25,并使用节点的新值ipaddr
来定位它。
xmlstarlet ed \
-u '//ipaddr[. = "192.168.1.1" and following-sibling::subnet[1] = "24"]' -v '192.168.1.125' \
-u '//subnet[. = "24" and preceding-sibling::ipaddr[1] = "192.168.1.125"]' -v 25 file.xml
结果将是
<?xml version="1.0"?>
<root>
<ipaddr>192.168.1.2</ipaddr>
<subnet>24</subnet>
<ipaddr>192.168.1.125</ipaddr>
<subnet>25</subnet>
</root>
ipaddr
如果和subnet
节点是同一父节点的子节点,则该命令会简单得多并且不易出错,如下所示
<?xml version="1.0"?>
<root>
<host name="hostA">
<ipaddr>192.168.1.2</ipaddr>
<subnet>24</subnet>
</host>
<host name="hostB">
<ipaddr>192.168.1.1</ipaddr>
<subnet>24</subnet>
</host>
</root>
然后我们可以简单地选择host
节点的名称,如下所示:
xmlstarlet ed \
-u '//host[@name="hostB"]/ipaddr' -v '192.168.1.125' \
-u '//host[@name="hostB"]/subnet' -v '25' file.xml
生产
<?xml version="1.0"?>
<root>
<host name="hostA">
<ipaddr>192.168.1.2</ipaddr>
<subnet>24</subnet>
</host>
<host name="hostB">
<ipaddr>192.168.1.125</ipaddr>
<subnet>25</subnet>
</host>
</root>