0

I have a config file as hive-site.xml

One configuration element is;

  <property>
    <name>hadoop.embedded.local.mode</name>
    <value>true</value>
  </property>

I want to change the "true" to "false" by a shell script. But in the file there are lots of configuration elements such as;

   <value>true</value> 

tags.

So the "sed" command I used to find and replace strings is difficult to be used here with my knowledge. Appreciate if anyone can help me with this.

3
  • 1
    I suggest you use a Proper Programming Language with an XML parsing library. Commented Apr 18, 2013 at 4:33
  • So are you saying it is impossible to do this with a shell script ? Commented Apr 18, 2013 at 4:45
  • Not impossible, but very very difficult. (I would have serious trouble parsing XML in a shell script.) Commented Apr 18, 2013 at 4:49

5 Answers 5

1

This is probably a job for XPath and a reasonable XML library. Doing this from a shell script directly is going to create a complicated and likely fragile solution. I'm going to use python and the popular lxml library as an example:

from lxml import etree

tree = etree.fromstring('''
  <property>
    <name>hadoop.embedded.local.mode</name>
    <value>true</value>
  </property>
''')

e = tree.xpath('//property[name="hadoop.embedded.local.mode"]/value')[0]
e.text = 'false'
print etree.tostring(tree)

Basically that selects any property node (anywhere in the doc) if it contains a <name> element with that value, then it selects the value element. You can then modify the element's content to your liking and print as a string again. XPath is standard, so roughly the same code ought to work in other implementations as well.

Sign up to request clarification or add additional context in comments.

Comments

1

Obviously quite a few ways to do this, but why not try awk (gawk)?

#!/bin/bash

gawk \
'        
    BEGIN {
        FLAG = 0;
    }

    /hadoop.embedded.local.mode/ {
        FLAG = 1;
    }

    />[     ]*true[     ]*</ {
        if (FLAG == 1) {
            FLAG = 0
            gsub("true", "false")
        }
    }

    {
        print
    }
' "$@"

Invoke the above script as:

<script> hive-site.xml

Comments

0

You can give the whole block and change.

sed -i '/s/<property><name>hadoop.embedded.local.mode<\/name><value>true<\/value<\/property>
/<property><name>hadoop.embedded.local.mode<\/name><value>false<\/value><\/property>/' 
hive-site.xml

2 Comments

You need to escape the embedded slashes, or use a different delimiter. And do multi-line replacements really work? I thought sed operated a line at a time.
yes correct we need to escape slashes and multi-line replacements worked for me
0

If the value you want to change is always on the next line you can first get the line number of the desired element with

NUMBER=$(grep -n "<desired element>" filename | awk -F: '{print $1}')

Then increment to the next line

let NUMBER="NUMBER + 1"

Then use sed or ex to modify the value, I prefer ex in these cases, as it eliminates the need for an interim text file.

{
print "${NUMBER}s/true/false/"
print "wq"
} | ex filename 

Comments

0

sed javax.jdo.option.ConnectionURL

new_val="Chandu_jdbc" sudo sed -i "/javax.jdo.option.ConnectionURL/!b;n;c${new_val}" /tmp/hive-site.xml sudo sed -i '/javax.jdo.option.ConnectionURL/!b;n;c'${new_val}' /tmp/hive-site.xml sudo sed -i "/javax.jdo.option.ConnectionURL/!b;n;c${new_val}" /tmp/hive-site.xml sudo sed -i '/javax.jdo.option.ConnectionURL/!b;n;c'"${new_val}"'' /tmp/hive-site.xml

1 Comment

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.