String substitution

Hi,

I have a properties file (myprop.properties) which contains some values:
@oneValue@==tcp://localhost:1234
@twoValue@==tcp://localhost:4563
@threeValue@==tcp://localhost7895

I have a xml file (myXmlFile.xml)which contains some tokens:
<application name="aTest">
<NameValuePair>
<name>firstName</name>
<value>@oneValue@</value>
</NameValuePair>
<NameValuePair>
<name>secondName</name>
<value>@twoValue@</value>
</NameValuePair>
</application>

I want to replace the tokens in the file myXmlFile.xml by the values of the myprop.properties. I did a script but I cannot manage to match the tokens with awk, I always get the string "nothing" any ideas?

#!/bin/ksh

exec 0< myXmlFile.xml

while read line
do
count=0

for token\_per_line in $\(cat myprop.properties\)
do
  
  first_char=\`echo $\{token\_per_line\} | cut -c1\`
        
  if [ "$first_char"  != "\#" ] && [ $count -lt 1 ]; then
      
      token_variables=\`echo "$token\_per_line" | grep -v '\#'| awk -F'==' '\{print $1\}'\` 
      token_values=\`echo "$token\_per_line" | awk -F'==' '\{print $2\}'\` 
                            
      echo $line | awk -v token\_var="$token_variables" token\_val="$token_values" '\{ 
         
        \{ 
          
          if \($0 ~ /token_var/\) \{ 
          print "matching"
          gsub\($token_variables, $token_values, $line\); 
          print $0
          \} 
          else \{
            print "nothing"                
          \}
        \} 
        
      \}'           
  count=$count\+1      
  fi      
done  

done
exec 0<&3

Regards
John

I hope I've understood what you wanted to do. Here's what I did:

1) Created a file called "values". It contains:

@oneValue@==tcp\:\/\/localhost\:1234
@twoValue@==tcp\:\/\/localhost\:4563
@threeValue@==tcp\:\/\/localhost\:7895

Note the escaped characters. I'm also assuming that you wanted a : before the 7895 on the last line.

2) Created a file called "file.xml". It contains:

<application name="aTest">
<NameValuePair>
<name>firstName</name>
<value>@oneValue@</value>
</NameValuePair>
<NameValuePair>
<name>secondName</name>
<value>@twoValue@</value>
</NameValuePair>
</application>

Third, used this tcsh foreach script:

foreach value ( `cat values` )
set val = `echo $value | awk -F"==" '{print $2}'`
set grp = `echo $value | awk -F"==" '{print $1}'`
sed -i .bak "s/$grp/$val/" file.xml
end

Now, since this uses sed -i, I strongly recommend backing up your .xml file before running this. I've never had sed -i fail me, but your mileage may vary drastically.

If your file corresponding to my values file is long and tedious to escape like I did above, you can use this to rewrite it:

cat values | sed -e 's/\//\\\//g' -e 's/:/\\:/g' >> newvalues

Strictly speaking, it's not necessary to cat the file into sed. Oh, well. Also, the -i can be used here as well, but I tend to err on the side of paranoia where sed -i and other file-overwrite ops are concerned. Lemme know if anything's unclear... my writing can be that way sometimes. :slight_smile:

Or,

awk -F'@|==' 'NR==FNR{ a[$2]=$4; next } $2 in a{ $2=a[$2]; OFS=""; print; next }1'  properties_file xml_file
$ cat properties_file

@oneValue@==tcp://localhost:1234
@twoValue@==tcp://localhost:4563
@threeValue@==tcp://localhost7895
$ cat xml_file

<application name="aTest">
<NameValuePair>
<name>firstName</name>
<value>@oneValue@</value>
</NameValuePair>
<NameValuePair>
<name>secondName</name>
<value>@twoValue@</value>
</NameValuePair>
</application>

Output:

<application name="aTest">
<NameValuePair>
<name>firstName</name>
<value>tcp://localhost:1234</value>
</NameValuePair>
<NameValuePair>
<name>secondName</name>
<value>tcp://localhost:4563</value>
</NameValuePair>
</application>

perl:

open FH1,"<a";
while(<FH1>){
	@arr=split("=",$_);
	$arr[2]=~ tr/\n//d;
	$hash{$arr[0]}=$arr[2];
}
close FH1;

open FH1,"<b";
while(<FH1>){
	if(m/<value>/){
		@arr=split("[<|>]",$_);
		$_=~ s/$arr[2]/$hash{$arr[2]}/;
		print $_;
	}
	else{
		print;
	}
}
close FH1;