Reputation:
I have an xml file that look something like this
<Process label="TRAM_FIT_TM_SERVER" machine="&HOSTNAME_TRAM;">
<Description>Monitor that TM SERVER stays up</Description>
<Enabled>true</Enabled>
<ProcessCheck method="ps">
<ProcName>.*bin/tmSrv -serverMode=tm</ProcName>
</ProcessCheck>
<Cmd>cd /ctec/apps/fotms/6.2/scripts/; ./tradeFlow.sh fitdev start tm > &LOGLOC;/fotms/logs/starttm.log</Cmd>
<KillCmd>pkill -u &USER; -f 'bin/tmSrv -serverMode=tm'</KillCmd>
<Count>1</Count>
<User>&USER;</User>
&EMAIL_SUPPORT;
&TRAM_SCHEDULE;
</Process>
There are about 40 odd of the processes, all with the same exact layout. I am able to read through the file in a while loop, stop at this specific Process using its Process label. Then I am able to grab the Enabled line, which is what I need to change like so.
while read line
do
if [[ "$line" == *"TRAM_FIT_TM_SERVER"* ]]
then
echo ...
var_checker=2
fi
if [[ "$line" == *"Enabled"* ]]
then
if [ "$var_checker" == 2 ]
then
#change value to false
#sed -i 's/true/false/g' $line
var_checker=1
echo "Changed trade server"
break 3
fi
fi
done <fit.core_tram.procmon.xml
My question is, how do I change the Enabled value of this process, and ONLY for this process to false. I need to use sed or grep if possible, and I unfortunately can't just do sed -i 's/true/false/g' filename due to the fact there being multiple occurrences of that exact setup. Any help would be appreciated
Upvotes: 2
Views: 107
Reputation: 295353
sed
is the wrong tool for this job; use an XML-aware tool such as XMLStarlet:
xmlstarlet ed \
-u '//Process[@label="TRAM_FIT_TM_SERVER"]/Enabled' \
-v false \
<in.xml >out.xml
This will modify the value for Enabled
for only a process with the exact label TRAM_FIT_TM_SERVER
to false
.
If you can't install XMLStarlet, consider taking advantage of the ubiquity of Python:
# note that since we're using ElementTree, not lxml.etree, this isn't "real" XPath
# ...however, it's good enough for your expression here.
#
# Switch to "import lxml.etree as etree" if you have the Python lxml package installed
# and want a more flexible syntax.
edit_value() {
local xpath=$1
local value=$2
python -c '
import sys
import xml.etree.ElementTree as etree
xpath=sys.argv[1]
value=sys.argv[2]
root = etree.parse(sys.stdin)
for el in root.findall(xpath):
el.text = value
root.write(sys.stdout)
' "$xpath" "$value"
}
...thereafter used as:
edit_value '//Process[@label="TRAM_FIT_TM_SERVER"]/Enabled' false \
<in.xml >out.xml
That said, to test either of these answers you need a version of your document that's complete enough to parse -- the original, as given, uses entities that it doesn't define. My answers above are tested against the following:
<!DOCTYPE opdef [
<!ENTITY HOSTNAME_TRAM "hostname">
<!ENTITY LOGLOC "logloc">
<!ENTITY USER "user">
<!ENTITY EMAIL_SUPPORT "[email protected]">
<!ENTITY TRAM_SCHEDULE "schedule">
]>
<root>
<Process label="TRAM_FIT_TM_SERVER" machine="&HOSTNAME_TRAM;">
<Description>Monitor that TM SERVER stays up</Description>
<Enabled>true</Enabled>
<ProcessCheck method="ps">
<ProcName>.*bin/tmSrv -serverMode=tm</ProcName>
</ProcessCheck>
<Cmd>cd /ctec/apps/fotms/6.2/scripts/; ./tradeFlow.sh fitdev start tm > &LOGLOC;/fotms/logs/starttm.log</Cmd>
<KillCmd>pkill -u &USER; -f 'bin/tmSrv -serverMode=tm'</KillCmd>
<Count>1</Count>
<User>&USER;</User>
&EMAIL_SUPPORT;
&TRAM_SCHEDULE;
</Process>
</root>
Upvotes: 4