Issue
I am trying to replace content by checking previous lines as well as the next line. As shown below.
<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>
Replace <IpAdd>any IP address</IpAdd>
with <IpAdd>111.111.111.111</IpAdd>
for which the next line is <port>1123</port>
and it should be under <Info><pInfo>"eth0"</pInfo>
section.
What I tried:
sed -E "/<Info>/{n;/<pInfo>/{n;s@<IpAdd>.*<([^\n]*\n[^\n]*<port>1123</port>)@<IpAdd>111.111.111.111<@}}" test.txt
Want to replace in the line above port 1123. If I remove ([^\n]*\n[^\n]*<port>1123</port>)
, then it replaces both ips under Info.
<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>
Expect:
<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>
Solution
This might work for you (GNU sed):
sed -E '/<Info>/{:a;N;/<\/Info>$/!ba
s/(<IpAdd>).*(<\/IpAdd>\n<port>1123<\/port>)/\1111.111.111.111\2/}' file
Gather up the lines between <Info>
and </Info>
and then match the two lines within the collection that start with <IpAddr>
and end with 1123</port>
and replace the old address with the new address.
Answered By - potong Answer Checked By - David Goodson (WPSolving Volunteer)