我试图通过检查前一行和下一行来替换内容。如下所示。
<Info>
<pInfo>"eth0"</pInfo>
<IpAdd>192.168.1.2</IpAdd>
<port>1123</port>
</Info>
<Info>
<pInfo>"eth1"</pInfo>
<IpAdd>192.168.1.22</IpAdd>
<port>6789</port>
</Info>
<User>
<avl>"Name"</avl>
<IpAdd>192.168.1.2</IpAdd>
<port>1123</port>
</User>
将<IpAdd>any IP address</IpAdd>
替换为<IpAdd>111.111.111.111</IpAdd>
,下一行是<port>1123</port>
,并且应该在<Info><pInfo>"eth0"</pInfo>
部分下。
我尝试的是:
sed -E "/<Info>/{n;/<pInfo>/{n;s@<IpAdd>.*<([^\n]*\n[^\n]*<port>1123</port>)@<IpAdd>111.111.111.111<@}}" test.txt
要替换端口1123以上的行。如果我删除([^\n]*\n[^\n]*<port>1123</port>)
,那么它将替换Info下的两个ips。
<Info>
<pInfo>"eth0"</pInfo>
<IpAdd>111.111.111.111</IpAdd>
<port>1123</port>
</Info>
<Info>
<pInfo>"eth1"</pInfo>
<IpAdd>111.111.111.111</IpAdd>
<port>6789</port>
</Info>
<User>
<avl>"Name"</avl>
<IpAdd>192.168.1.2</IpAdd>
<port>1123</port>
</User>
预期:
<Info>
<pInfo>"eth0"</pInfo>
<IpAdd>111.111.111.111</IpAdd>
<port>1123</port>
</Info>
<Info>
<pInfo>"eth1"</pInfo>
<IpAdd>192.168.1.22</IpAdd>
<port>6789</port>
</Info>
<User>
<avl>"Name"</avl>
<IpAdd>192.168.1.2</IpAdd>
<port>1123</port>
</User>
4条答案
按热度按时间b5buobof1#
使用任何awk:
上面的代码假设Info块中的行的顺序实际上并不重要。
vybvopom2#
一个
awk
的想法:这产生:
tquggr8v3#
这可能对你有用(GNU sed):
收集
<Info>
和</Info>
之间的行,然后匹配集合中以<IpAddr>
开始并以1123</port>
结束的两行,并用新地址替换旧地址。fkaflof64#
TXR中的解决方案:
我扩大了数据,以测试更多的情况:这个模式在我的
<Info>
中出现了两次,我有一个<NotInfo>
元素,其中出现了这个模式,但不能编辑:它只在正确的地方编辑:
其中
edit.txr
:它的工作原理是,我们有一个外部
@(repeat)
,它正在进行滑动模式扫描,寻找两种情况:一个以<Info>
开始的块,或者一个匹配一行的后备情况,可以是任何东西。当回退情况发生时,输出该行。无论匹配的是什么,都会被消耗,因此扫描从下一行开始。主要情况以
<Info>
的匹配开始。如果成功,则输出<Info>
,并进行类似于外部扫描的嵌套扫描:查找要替换的三行模式,否则就只能使用并输出一行。内部@(repeat)
在看到</Info>
关闭标记时终止。