1

I have below command to find all the .xml files containing the <active>true</active> having <codePool>community</codePool> after that line on next line.

grep -rzl '<active>true</active>.*<codePool>community</codePool>' --include='*.xml' --color=always

Now how to combine this with sed to replace true string inside the <active>... tag to false string along those matched lines ?

  • Watch out, you might get an answer from this guy: stackoverflow.com/a/1732454/5851520 :-) – SusanW Nov 10 '16 at 11:22
  • ... which is why you have the -z in there. Good, good... – SusanW Nov 10 '16 at 11:49
  • Question: that grep will detect files where the codePool/community thing is anywhere in the file after the active bit. Is that ok? You say "on the next line", but the grep isn't caring about that. – SusanW Nov 10 '16 at 11:57
2

You should use XML parsing tools for XML data. xmlstarlet is a good choice. Regular expressions are just not powerful enough (canonical reference)

If your data looks like:

<root>
  <foo>
    <active>true</active>
    <codePool>private</codePool>
  </foo>
  <foo>
    <active>true</active>
    <codePool>community</codePool>
  </foo>
</root>

Then

xmlstarlet ed --update '//active[.="true" and ../codePool="community"]' -v false file.xml

produces

<?xml version="1.0"?>
<root>
  <foo>
    <active>true</active>
    <codePool>private</codePool>
  </foo>
  <foo>
    <active>false</active>
    <codePool>community</codePool>
  </foo>
</root>

Here's an awk program that does what you request. Keep in mind that it's fragile: if the input changes, this code will stop working. It does just use plain string operations.

awk '
    BEGIN {
        marker = "<codePool>community</codePool>"
        srch = "<active>true</active>"
        repl = "<active>false</active>"
    }
    index($0, marker) {
        i = index(prev, srch)
        if (i > 0) 
            prev = substr(prev, 1, i-1) repl substr(prev, i+length(srch))
    }
    {
        if (prev) print prev
        prev = $0
    }
    END {if (prev) print prev}
'
  • That canonical reference needs updating for XHTML->"XML generally". I fear the original author was eaten by Tony the Pony. – SusanW Nov 10 '16 at 15:06
  • @glennjackman, Your answer is quite well, but I am working on Remote SSH that is owned by client, so I don't have permission to install any third party software/library into his system. Please suggest also a ubuntu or any well-known linux command line alternative to this. – Vicky Dev Nov 10 '16 at 15:17
0

Thanks for the answer @glennjackman, I was also successfull achieving my requirement with the following code, it is vulnerable in-case the input changes, but it will be consistent keeping the fixed directory structure and file format of xml files of Magento, in mind:

for filename in *.xml; do
    if grep -q '<codePool>community</codePool>' "$filename"; then
        if [[ $filename != *"Mage_"* ]]; then
            sed -i.bak 's/<active>true<\/active>/<active>false<\/active>/g' "$filename"
        fi
    fi
done

This way I was also able to backup those files first, that were going to be modified, just the way I wanted.

Hope this simplifies things and redirects all/as many as possible people to using domestic libraries rather than installing third party tools which aren't allowed to install on Remote SSH/VPN networks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.