0

I want to replace a line which is 2 lines before the match/pattern but this match pattern is also getting repeated for 5 times in file and I want this replacement should happen only before the 5th match. For eg:

Input file

</alarmSpecification>
<alarmSpecification active="yes">
<moduleId>PSC-Task1111</moduleId>
<errorCode>444</errorCode>
</alarmSpecification>
<alarmSpecification active="yes">
<moduleId>PSC-Task2222</moduleId>
<errorCode>444</errorCode>
</alarmSpecification>
<alarmSpecification active="yes">
<moduleId>PSC-Task3333</moduleId>
<errorCode>444</errorCode>
</alarmSpecification>
<alarmSpecification active="yes">
<moduleId>PSC-Task4444</moduleId>
<errorCode>444</errorCode>
</alarmSpecification>
<alarmSpecification active="yes">
<moduleId>PSC-Task5555</moduleId>
<errorCode>444</errorCode>

Now I want replace "yes" to "no" in the 3rd last line. please remember line "444" is repeated 5 time in file and PSC-Task5555 is also repeated multiple times in entire file.

My requirement is in file, when we find below 2 combination of lines

<moduleId>PSC-Task5555</moduleId>
<errorCode>444</errorCode>

then replace the "yes" to "no" as below:

<alarmSpecification active="**no**">
<moduleId>PSC-Task5555</moduleId>
<errorCode>444</errorCode>

Thanks Ujjawal

3
  • Welcome! Is it not the 4th line, not the 3rd? Commented Mar 20, 2020 at 14:32
  • Please clarify if you're trying to match on the 5th occurrence of <moduleId>PSC-Task5555</moduleId>\n<errorCode>444</errorCode> (with those specific values), or just trying to update the 5th <alarmSpecification line or something else, i.e. tell us what the match/pattern actually IS in your question. Commented Mar 20, 2020 at 15:46
  • Hi, Situation is like ,I am upgrading a linux server. Post version upgrade, lot of new error codes and corresponding tasks (1111 or 2222 or3333 etc) will get added in alarms.xml file. Now I want to update "active=no" when I find below 2 parameters in consecutive lines. <moduleId>PSC-Task5555</moduleId> <errorCode>444</errorCode>. Please note that this error code (444) and taskID (task111 etc) will be there in alarm.xml many times. So I can not just match either of them and change the active=no. I have to make sure both lines are consecutive then change happen. Commented Mar 21, 2020 at 18:53

2 Answers 2

1

Assuming your xml is properly formed then you could use xmlstarlet

xmlstarlet edit --update \
    '//alarmSpecification[errorCode=444][moduleId="PSC-Task5555"]/@active' --value "no" file1

Output

<alarmSpecifications>
  <alarmSpecification active="yes">
    <moduleId>PSC-Task1111</moduleId>
    <errorCode>444</errorCode>
  </alarmSpecification>
  <alarmSpecification active="yes">
    <moduleId>PSC-Task2222</moduleId>
    <errorCode>444</errorCode>
  </alarmSpecification>
  <alarmSpecification active="yes">
    <moduleId>PSC-Task3333</moduleId>
    <errorCode>444</errorCode>
  </alarmSpecification>
  <alarmSpecification active="yes">
    <moduleId>PSC-Task4444</moduleId>
    <errorCode>444</errorCode>
  </alarmSpecification>
  <alarmSpecification active="no">
    <moduleId>PSC-Task5555</moduleId>
    <errorCode>444</errorCode>
  </alarmSpecification>
</alarmSpecifications>
0

Tried with Below command and it worked fine

g=`awk 'END{print NR}' test.txt `

for ((i=1;i<=$g;i++)); do j=$(($i+3)); sed -n ''$i','$j'p' test.txt| perl -pne "s/\n/ /g"| awk '/444/&&/PSC-Task5555/{gsub("yes","**no**",$0)}1'; i=$j;echo -e "\n"; done| sed "s/> />\n/g"| sed '/^$/d'

output

</alarmSpecification>
<alarmSpecification active="yes">
<moduleId>PSC-Task1111</moduleId>
<errorCode>444</errorCode>
</alarmSpecification>
<alarmSpecification active="yes">
<moduleId>PSC-Task2222</moduleId>
<errorCode>444</errorCode>
</alarmSpecification>
<alarmSpecification active="yes">
<moduleId>PSC-Task3333</moduleId>
<errorCode>444</errorCode>
</alarmSpecification>
<alarmSpecification active="yes">
<moduleId>PSC-Task4444</moduleId>
<errorCode>444</errorCode>
</alarmSpecification>
<alarmSpecification active="**no**">
<moduleId>PSC-Task5555</moduleId>
<errorCode>444</errorCode>

Method2: Python

#!/usr/bin/python
import re
u=[]
l=re.compile(r'444')
e=re.compile(r'PSC-Task5555')
k=open('test.txt','r')
p=k.readlines()
print len(p)

for o in range(0,len(p),4):
    u.append("".join(p[o:o+4]).replace("\n"," "))

for g in u:
    if re.search(l,g) and re.search(e,g):
        print re.sub("yes","**no**",g).replace("> ",">\n").strip()
    else:
        print g.replace("> ",">\n").strip()

output

</alarmSpecification>
<alarmSpecification active="yes">
<moduleId>PSC-Task1111</moduleId>
<errorCode>444</errorCode>
</alarmSpecification>
<alarmSpecification active="yes">
<moduleId>PSC-Task2222</moduleId>
<errorCode>444</errorCode>
</alarmSpecification>
<alarmSpecification active="yes">
<moduleId>PSC-Task3333</moduleId>
<errorCode>444</errorCode>
</alarmSpecification>
<alarmSpecification active="yes">
<moduleId>PSC-Task4444</moduleId>
<errorCode>444</errorCode>
</alarmSpecification>
<alarmSpecification active="**no**">
<moduleId>PSC-Task5555</moduleId>
<errorCode>444</errorCode>
2
  • Thanks alot It worked. Thanks Buddy. Commented Mar 23, 2020 at 8:58
  • @Ujjawal KIndly upvote my answer Commented Mar 23, 2020 at 9:01

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.