-1

With the conditions:

  1. I cannot use any XML parser tool as I don't have permission , read only

  2. My xmllint version does not support xpath, and I cannot update it , read only

  3. I dont have xmlstarlet and cannot install it

  4. I run my script using Java JSch exec channel ( I have to run it here )

So we have 3 files in a directory.

  1. sample.xml
  2. values1.properties
  3. values2.properties

The contents of the files are as follows:

Sample.xml

<block> <name>Bob</name> <address>USA</address> <email>$BOB_EMAIL</email> <phone>1234567</phone> </block> <block> <name>Peter</name> <address>France</address> <cell>123123123</cell> <drinks>Coke</drinks> <car>$PETER_CAR</car> <bike>Mountain bike</bike> </block> <block> <name>George</name> <hobby>$GEORGE_HOBBY</hobby> <phone>$GEORGE_PHONE</phone> </block> 

values1.properties

[email protected] [email protected] [email protected] [email protected] [email protected] GEORGE_PHONE=Samsung 

values2.properties

JOE_CAR=Honda DAISY_CAR=Toyota PETER_CAR=Mazda TOM_CAR=Audi BOB_CAR=Ferrari GEORGE_HOBBY=Tennis 

I use this script to get the xml block to be converted to a properties file format

NAME="Bob" sed -n '/name>'${NAME}'/,/<\/block>/s/.*<\(.*\)>\(.*\)<.*/\1=\2/p' sample.xml 

OUTPUT:

name=Bob address=USA email=$BOB_EMAIL phone=1234567 

How do I get the value of $BOB_EMAIL in values1.properties and values2.properties. Assuming that I do not know where it is located between the two (or probably more) properties file. Bacause it should work differently if I entered

Name=Peter 

in the script, it should get

name=Peter address=France cell=123123123 drinks=Coke car=$PETER_CAR bike=Mountain bike 

and the think that will be searched will be PETER_CAR

EXPECTED OUTPUT (The user only needs to input 1 Name at a time and the output expected is one set of data in properties format with the $PLACEHOLDER replaced with the value from the properties file):

User Input: Name=Bob

name=Bob address=USA [email protected] phone=1234567 

User Input: Name=Peter

name=Peter address=France cell=123123123 drinks=Coke car=Mazda bike=Mountain bike 

Ultimately, the script that I need has this logic:

  1. for every word with $
  2. in the result of sed -n '/name>'${name}'/,/<\/block>/s/.*<(.*)>(.*)<.*/\1=\2/p' sample.xml ,
  3. it will search for the value of that word in all of the properties file in that directory(or specified properties files),
  4. then replace the word with $ with the value found in the properties file

PARTIALLY WORKING ANSWER:

Walter A's answer is working in cmd line (putty) but not in Jsch exec. I keep getting an error of No value found for token 'var' .

7
  • unix.stackexchange.com/q/211949/13792 Commented Jun 24, 2015 at 20:57
  • How about x=$(sed -n '/name>'${NAME}'/,/<\/block>/s/.*<\(.*\)>\(.*\)<.*/\1=\2/p' sample.xml); echo "$x" Commented Jun 24, 2015 at 21:20
  • @Walter it still displayed the value with placeholder, the values that I need there are in the properties file Commented Jun 24, 2015 at 22:07
  • Your conditions are making it very difficult to perform your job. Commented Jun 25, 2015 at 14:01
  • @glennjackman what do I need to parse through properties files and look for the placeholders value? Commented Jun 25, 2015 at 14:42

3 Answers 3

1
+50

The solution beneath will look in the properties files a lot of times, so I think there is a faster solution for the problem.
The solution beneath will get you started and with small files you might be happy with it.

# Question has a bash en ksh tag, choose the shebang line you want # Make sure it is the first line without space or ^M after it. #!/bin/ksh #!/bin/bash # Remove next line (debugging) when all is working # set -x for name in Bob Peter; do sed -n '/name>'${name}'/,/<\/block>/s/.*<\(.*\)>\(.*\)<.*/\1=\2/p' sample.xml | while IFS="\$" read line var; do if [ -n "${var}" ]; then echo "${line}$(grep "^${var}=" values[12].properties | cut -d= -f2-)" else echo "${line}" fi done echo done 

EDIT: Commented two possible shebang lines, set -x and added output.

Result:

name=Bob address=USA [email protected] phone=1234567 name=Peter address=France cell=123123123 drinks=Coke car=Mazda bike=Mountain bike 
Sign up to request clarification or add additional context in comments.

18 Comments

Im getting No value found for token 'var'
can you explain to me where var is populated here?
I can not reproduce your problem. I tested it with bash but tried to use portable commands only. In the line while IFS="\$" read line var the variable var is filled when the line has a $ character or stays empty when there is no $. The next line should check the token. I will reverse the check (not -z but -n), maybe that helps. Some info about checking empty variables: checking vars.
-n did not work also. hmm . what is wrong . . I execute the script using Jsch's exec channel.
Ahh. Jsch might do or omit other things. 1. Please test my script from the command-line. 2. You can add #!/bin/ksh or #!/bin/bash as the first line, that might overrule Jsch specific behaviour.
|
1
. values1.properties . values2.properties sed -n '/name>'${NAME}'/,/<\/block>/s/.*<\(.*\)>\(.*\)<.*/echo \1="\2"/p' sample.xml >output . output 

Dangerous, and not the way I would prefer to do it.

6 Comments

Im getting Exit Code: 1
The . sources the file. Basically executes it in your current shell, which assigns all the variables.. ie PETER_EMAIL, etc. Your variables are then expanded when the output is sourced.
Im using JSch's exec channel to execute my script. Is this the problem?
I tried something like this first, but had problems with bike=Mountain bike. Additionally vars containing quotes will also be evaluated.
Sourcing was a cool way! But dangerous too... +1 since you have included the warning too..
|
0

A sed based version:

$ temp_properties=`mktemp` $ NAME=Bob $ sed '/./{s/^/s|$/;s/=/|/;s/$/|g/}' values*.properties > $temp_properties $ sed -n '/name>'${NAME}'/,/<\/block>/s/.*<\(.*\)>\(.*\)<.*/\1=\2/p' sample.xml | sed -f $temp_properties 

Gives:

name=Bob address=USA [email protected] phone=1234567 

It does have issues of script injection. However, if you trust the values*.properties files & contents of NAME variable, you are good to go.

6 Comments

Did you by any chance miss out any character in above snippet? These command run as-are on my system.
sed: file /tmp/tmp.YUHfVm4670 line 229: unterminated `s' command - Still getting this
Does your file have crlf line endings? check file values*.properties... If yes, you can change using dos2unix filename...
^^ Does your file have crlf line endings? I could still have got alternate ways, if you had also answered that... :D
sed '/./{s/\r//;s/^/s|$/;s/=/|/;s/$/|g/}' values*.properties > $temp_properties
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.