XML- Sed || Awk Bash script... Help!

Hi ! I'm working into my first bash script to make some xml modification and it's going to make me crazy lol .. so I decide to try into this forum to take some ideas from people that really know about this!

This is my situation I've and xml file with a lots of positional values with another tags too but this are the importants tags

<x>28.981743194648736</x>
<y>72.4853691731618</y>
<z>0.0</z>
<x>53.46605522341658</x>
<y>54.678596788603365</y>
<z>0.0</z>

and this continue with differents values in the same way
I need to change all the values of x tags by new ones, particulary with random numbers.. the problem that I've is that I have succes to change that values but..... ! , sed change me the value of all the <x> </x> tags with the same value and I need that all that values were differents.. here my code

#!/bin/bash
NUM=0

while [ $NUM -le 20 ]; do
NUM1=$(echo "scale=3;((${RANDOM})/1000)" |bc)
echo "$NUM1"
sed 's/<x>[-[:alnum:]./]\{1,\}<\/x>/<x>'$NUM1'<\/x>/' myfile.xml > newfile.xml

echo "\$NUM: $NUM"
let NUM=$NUM+1
done

THANKS FOR YOUR TIME ANY IDEA WOULD BE WELCOME !!!

line-basedtools like awk, sed, shells, aren't very good at handling xml because they're not recursive parsers. (Well, it parses THEIR language recursively, but doesn't parse text they read in recursively -- things like yacc do..) Usually you'd use a language like perl or python and load an xml module. Could you tell us what your actual goal is instead of the way you want to do it?

note that everytime your run this script, you get the same x value in same line. but in the file, every x-value should be unique. If you want to get different x-value in each run, change the srand seed please.

awk '/x/{srand(NR);v=rand()*50+1;$0="<x>"v"</x>"};1' yourFile

output:

<x>12.8894</x>
<y>72.4853691731618</y>
<z>0.0</z>
<x>37.5135</x>
<y>54.678596788603365</y>
<z>0.0</z>
1 Like

Thanks Corona668 and sk1418 for your time ! . .

sk1418 your code works like a charm! thanks for your help !, another question...... sorry if I bother you, I almost know nothing of awk , you can put the "output" in a new file like in sed ? and another thing ! you can define how many decimals you need ? like 3.444 or 3.44444444

sed 's/<x>[-[:alnum:]./]\{1,\}<\/x>/<x>'$NUM1'<\/x>/' cornodobeta2.xml > newfile.xml

I tried with > newfile.xml but no lucky

Thanks for your help !!

For your Q1: write the output to a new file is as easy as:

awk ... inputFile > yourNewFile

Q2: with precision control:

awk '/x/{srand(NR);v=rand()*50+1;printf  "<x>%.13f</x>\n",v};!/x/'

you can change the "%.13f" to your wish to control the precision. the output of above line with %.13f looks like:

<x>12.8893756120882</x>
<y>72.4853691731618</y>
<z>0.0</z>
<x>37.5135307593800</x>
<y>54.678596788603365</y>
<z>0.0</z>
1 Like

Man ... you're simply awesome!
Supose that in the future I need to change the <y> value too, with a value distinct to the x and also random the code will be this ?

awk '/x/{srand(NR);v=rand()*50+1;$0="<x>"v"</x>"};1' myfile.xml > filemod.xml
awk '/y/{srand(NR);v=rand()*50+1;$0="<y>"v"</y>"};1' myfile.xml > filemod.xml

because it doesn't give me the expected result .

Here I Post part of the exactly xml that I'm working .

<mote> 
      <interface_config> 
        se.sics.cooja.interfaces.Position 
        <x>53.39887462699737</x> 
        <y>66.79001043503861</y> 
        <z>0.0</z> 
      </interface_config> 
      <interface_config> 
        se.sics.cooja.contikimote.interfaces.ContikiMoteID 
        <id>4</id>

Thanks Again for your Time and your experience in this !

you can change the random seed to get different random number for your 'y'.
eg

awk '/y/{srand(NR*2);v=rand()*77+1;$0="<y>"v"</y>"};1' myfile.xml > filemod.xml

I think it would be ok. (I didn't test).

In fact the easiest way to get a new y is do some math calculation on generated x. e.g. sqr(x) or x + a magic number ...

1 Like

Hi sk1418 thanks for your help !, I'm having a problem with the script , when I run this into all the xml file , when it found some word with an x into the words for eg <success_ratio_tx>1.0</success_ratio_tx> it change the value too and the result is this <x>30.7032</x> ... It was my fault because I didn't tell you all my xml file, is there a way that awk just take the exactly <x>..</x> tags ?

Thanks Again for your time , and sorry to be so newbie in this.:wall:

awk '/<x>/{srand(NR);v=rand()*50+1;printf  "<x>%.13f</x>\n",v};!/<x>/'                                                                                        
1 Like

Thanks man ! , Now it's working ok . I really appreciate your time helping me in this work !.