No one has said it yet, so I will. PLEASE don't parse XML using regular expressions. XML is a contextual language, and regular expressions aren't. This means you create brittle code, that one day might just break messily.
For more examples, see: https://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags
PLEASE use a parser. They exist in many languages - personally, I like perl
, and your task goes a bit like this:
#!/usr/bin/env perl use strict; use warnings; #parser library use XML::Twig; #ingest data my $twig = XML::Twig -> parse (\*DATA); #iterate all tags <ThreadGroup> foreach my $group ( $twig -> get_xpath('//ThreadGroup') ) { #check testname regex match if ( $group -> att('testname') =~ /AA/ ) { #set enabled $group -> set_att('enabled', 'true'); } else { #set disabled $group -> set_att('enabled', 'false'); } } #pretty print options vary, see man page. $twig -> set_pretty_print('indented_a'); $twig -> print; __DATA__ <xml> <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="OO CSS DPM PRI" enabled="true" /> <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="AA CSS DPM PRI" enabled="true" /> </xml>
And yes - it is necessary to use an XML parser, because regular expressions cannot do it safely. There are bunch of things in XML that are semantically identical, like attribute ordering, line feeds, unary tags etc. that aren't the same regex. But a parser won't be caught out by it.
The above can be cut down to a one liner if you prefer:
perl -MXML::Twig -e 'XML::Twig -> new ( twig_handlers => { ThreadGroup => sub { $_ -> set_att("enabled", $_ -> att("testname") =~ /AA/ ? "true" : "false" ) } } ) -> parsefile_inplace("yourfile")'
Your sysadmin team should thank you for doing this (that's not to say they will) because any solution based on regular expressions might break one day, for no apparent reason.
As a most trivial example - your XML is semantically identical as:
<xml> <ThreadGroup enabled="true" guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="OO CSS DPM PRI" /> <ThreadGroup enabled="true" guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="AA CSS DPM PRI" /> </xml>
Or:
<xml> <ThreadGroup enabled="true" guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="OO CSS DPM PRI"/> <ThreadGroup enabled="true" guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="AA CSS DPM PRI"/> </xml>
Or:
<xml><ThreadGroup enabled="true" guiclass="ThreadGroupGui" testclass="ThreadGrou p" testname="OO CSS DPM PRI"/><ThreadGroup enabled="true" guiclass="ThreadGroupG ui" testclass="ThreadGroup" testname="AA CSS DPM PRI"/></xml>
Or:
<xml ><ThreadGroup enabled="true" guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="OO CSS DPM PRI" /><ThreadGroup enabled="true" guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="AA CSS DPM PRI" /></xml>
And that's before we get into attribute ordering, possible tag nesting, or other substring that 'match' in places you won't expect.
xmlstarlet
for example. Or one of the many XML libraries for languages likeperl
orpython
, or almost any other language you might care to write in.sed
can in some very specific and simple cases make some simple changes to a text stream that happens to contain XML. It can't, in the general case, reliably edit XML. Neither can any other regular-expression based method or tool. The only way to do it reliably is to use an XML parser. If you can't convince the sysad team to install any extra tools, what language is used for your main production code? There will probably be an XML parser for that....if your code is producing XML output or uses XML data then you probably even have it already installed.sed
. That's about on a par with putting screws in with a hammer. It sort of works, but the result is ugly and not as robust. And a screwdriver isn't exactly a hard thing to acquire.