Hello all,
I try to create a bash script but till now without any positiv results.
The script should replace different variables in a text file with the right xml values
Look at the following xml file:
file.xml
===================================
<?xml version="1.0" encoding="UTF-8"?>
<Daten>
<export_date>2008-07-15 16:29:01</export_date>
<language>english</language>
temp.txt
===================================
All dates were exported at <export_date>
The text was translated in <language>
script.sh
===================================
#!/bin/bash
IFS=$'\n'
for i in `cat file.xml | sed 's/>/ /g' | awk '{print $1}' | sed 's/</ /g' | sed 's/ //g'`
do
for j in \`grep "$i" temp.txt | sed 's/.*<//g'| sed 's/>.*//g' \`
do
\#echo $j
for h in `cat temp.txt | sed -e "s/"$j"/$(cat file.xml | grep "$j" | sed 's/>/ /g' | sed 's/</ /g' | awk '{print $2}')/g" >> temp2 `
do
echo $h
done
done
done
The aim should be
All dates were exported at 2008-07-15 16:29:01
The text was translated in english.
Do you know how I could work on this?
thx
Hi,
first save the desired information in two variables using process substitution:
read date lang < <(sed -n "s#.*date>\(.*\)</.*#\1#p;s#.*age>\(.*\)</lan.*#\1#p" file.xml)
Then substitute the markers in the temp file:
sed "s/<export_date>/${date}/;s/<language>/${lang}/" temp.txt
HTH Chris
Sorry,
little typo. It must be:
{read date; read lang} < <(sed -n "s#.*date>\(.*\)</.*#\1#p;s#.*age>\(.*\)</lan.*#\1#p" test)
And if that doesn't work (it did on zsh but not on bash):
set -- $(sed -n "s#.*date>\(.*\)</.*#\1#p;s#.*age>\(.*\)</lan.*#\1#p" file.xml )
sed "s/<export_date>/${1} ${2}/;s/<language>/${3}/" temp.txt
Thanks a lot.
That has been helpful to me!
My last issue is that the original xml file included 420 lines.
Therefore if I create now all the variables manual and in the future will be change one line in the xml file or temp.txt, then I'm lost.
Have you any idee how can I use a simply way?
THX
ah, i see, try:
while IFS="><" read a id val b
do
sed -n "s#<${id}>#${val}#p" temp.txt
done < file.xml >> output
This will print the substitutions to a file called output.
super recognition,
but if the temp.txt include some others line without variables "exp. just a text line" will be not forwarded to the output. Or some variables in xml file is empty will be also dropped.
I don't understand what you mean by your second point "Or some variables
in xml file is empty will be also dropped." The first problem should be solved.
But if you have two files with arbitrary data in them, you will have to use
more powerful tools like awk or perl and provide some more lines of examples of input and desired output.
while IFS=">" read a id val
do
if [[ "$id" =~ "</" ]] then
VAL=${id%<*}; ID=${id#*</}
sed "s/<${ID}>/${VAL}/" temp.txt >> temp
mv temp temp.txt
fi
done < file.xml
With the second point I mean if not values are setting exp. <test></test>.
You are right, with perl or awk is more easy to finish this task but unfortunately I don't have any experience in awk or perl.
Whatever the stdout now is:
Syntax error: "fi" unexpected (expecting "then")
Try to think a little bit. There will be no stdout as the output is
redirected to file called temp and under bash you have to put
the "then" on a new line.
while IFS=">" read a id val
do
if [[ "$id" =~ "</" ]]
then
VAL=${id%<*}; ID=${id#*</}
sed "s/<${ID}>/${VAL}/" temp.txt >> temp
mv temp temp.txt
fi
done < file.xml
�Try to think a little bit. � it's difficult to think at 3'o clock in the morning.
The script works, there is only one mistake left. If the variable of the xml file contains a slash, for example <Name>I/you/he/she/</Name> than the sed doesn't work.
My suggestion would be:
VAL1=$(echo "$id" | sed 's/\//\\\//g' | sed 's/</ </g' | awk '{print $1}')
sed "s/<${ID}>/${VAL1}/" temp.txt >> temp
Unfortunately other xml records will be ignored after the first column.
Exp. <Firstname>Jan Janus</Firstname>
In this example only the record Jan is recognized.
This is the new xml-file with your previously unmentioned special cases:
<?xml version="1.0" encoding="UTF-8"?>
<Daten>
<export_date>2008-07-15 16:29:01</export_date>
<language>english</language>
<Name>I/you/he/she/</Name>
<Firstname>Jan Janus</Firstname>
This is the code:
while IFS=">" read a id val
do
if [[ "$id" =~ "</" ]]
then
VAL=${id%<*}; ID=${id#*</}
sed "s|<${ID}>|${VAL}|" temp.txt >> temp
mv temp temp.txt
fi
done < file.xml
This is my output:
All dates were exported at 2008-07-15 16:29:01
The text was translated in english
And his name is I/you/he/she/
And his other name ist Jan
Notice, everything you had to change was replace the
"/" with "|" in the above sed statement.
For me the above code works flawlessly under zsh and bash.
Or with escaped slashes:
#!/bin/bash
while IFS=">" read a id val
do
if [[ "$id" =~ "</" ]]
then
VAL=${id%<*}; ID=${id#*</}
VAL=${VAL//\//\\\/};ID=${ID//\//\\\/};
sed "s/<${ID}>/${VAL}/" ~/temp.txt >> ~/temp
mv ~/temp ~/temp.txt
fi
done < ~/file.xml
In the above output example the Janus after Jan is missing
(the script works but not my mouse).
But if there are still more special cases i would throw the script
away and start from scratch with perl or awk.
Christoph, thank you so much for your help.
I really appreciate it.
thx