2

Purpose is to generate XML file based on flat file , using awk. I managed to do it by pure coding. (print " .. etc . But I want a more awk-way by using printf fmt .

Input file (there are more similar lines) - I did not mention header lines (title : map entries mem) .

Mapone        5        10
Maptwo       12        45 
Maptree       8         7

Result file should be like :

<Map>Mapone</Map>
   <entries>5</entries>
   <mem>10</mem>   
<Map>Maptwo</Map>
   <entries>12</entries>
   <mem>45</mem>   
<Map>Maptree</Map>
   <entries>8</entries>
   <mem>7</mem>   

Currently i use

BEGIN {FS=" " ;

print "<?xml version=\"1.0\"?>";
}

{  Map = $1; }
{  Entry = $2;}
{  mem = $4;}

{
fmt = fmt "\t<Mapname>%s</Mapname>\n";
fmt = fmt "\t\t<Entries>%s</Entries>\n";
fmt = fmt "\t\t<Mem>%s</Mem>\n";

printf fmt, Map, Entry, mem ;

}

===> this script result in error containing "awk: There are not enough parameters in printf statement"

4
  • Your printf statement should be something like printf "%s %s %s %s", fmt, Map, Entry, mem ;. You are missing that. Commented Dec 31, 2015 at 11:29
  • You never clear fmt, so after the first line it has too many arguments. Either clear it or print once in an END statement Commented Dec 31, 2015 at 11:42
  • @fedorqui That would also fail as they are using fmt as the format so don't require the first bit in your example Commented Dec 31, 2015 at 11:43
  • @123 oh right, you are correct. I wasn't aware a string could be given to printf with all the placeholders. Commented Dec 31, 2015 at 11:44

1 Answer 1

4

Very simple change

You never clear fmt, so after the first line it has too many arguments

BEGIN{
print "<?xml version=\"1.0\"?>";
}

{  Map = $1; }
{  Entry = $2;}
{ mem = $3;  }

{

fmt = "\t<Mapname>%s</Mapname>\n"
#^ this will overwrite the previous fmt, so you won't have too many args.
fmt = fmt "\t\t<Entries>%s</Entries>\n"
fmt = fmt "\t\t<Mem>%s</Mem>\n"

printf fmt, Map, Entry, mem ;

}

The above will work although it's still written pretty horribly

I personally would set fmt once in the BEGIN block like below

BEGIN{
print "<?xml version=\"1.0\"?>";
fmt = "\t<Mapname>%s</Mapname>\n"
fmt = fmt "\t\t<Entries>%s</Entries>\n"
fmt = fmt "\t\t<Mem>%s</Mem>\n"
}
{
Map = $1
Entry = $2
mem = $3
printf fmt, Map, Entry, mem
}

As you can see i have also consolidated the block as there are no arguments for executing it, so it makes (IMO) clearer that it all those commands are executed every line.
I also removed they ; as the are not required unless you are not using linebreaks and changed mem to $3 as there are only 3 fields.

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

1 Comment

A simple printf fmt, $1, $2, $3 would be just as clear. Don't need the variables at all.

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.