2

I'm trying to create a script in (g)AWK in which I'd like to put the following EXACT lines at the beginning of the output text file:

<?xml version="1.0" encoding="UTF-8"?>
<notes version="1">
    <labels>
        <label id="0" color="30DBFF">Custom Label 1</label>
        <label id="1" color="30FF97">Custom Label 2</label>
        <label id="2" color="E1FF80">Custom Label 3</label>
        <label id="3" color="FF9B30">Custom Label 4</label>
        <label id="4" color="FF304E">Custom Label 5</label>
        <label id="5" color="FF30D7">Custom Label 6</label>
        <label id="6" color="303EFF">Custom Label 7</label>
        <label id="7" color="1985FF">Custom Label 8</label>
    </labels>

and this one to the end:

</notes>

Here is my script so far:

BEGIN       {printf("<?xml version="1.0" encoding="UTF-8"?>\n") > "notes.sasi89.xml"}

END         {printf("</notes>") > "notes.sasi89.xml"}

My problem is that it's not printing the way I'd like, it gives me this in the output file:

<?xml version=1 encoding=-8?>
</notes>

Some characters and quotes are missing, I've tried studying manuals but those are sound too complicated to me, I would appriciate if someone would give me a hand or put me to the right direction.

sasieightynine
  • 434
  • 1
  • 5
  • 16

1 Answers1

2

Answer is Community Wiki to give what credit can be given where credit is due.

Primary problem and solution

As swstephe noted in a comment:

You need to escape your quotes:

printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")

Anti-patterns

I regard your outline script as an anti-pattern (actually, two anti-patterns). You have:

BEGIN       {printf("<?xml version="1.0" encoding="UTF-8"?>\n") > "notes.sasi89.xml"}
END         {printf("</notes>") > "notes.sasi89.xml"}

The anti-patterns are:

  1. You repeat the file name; you shouldn't. You would do better to use:

    BEGIN {file = "notes.sasi89.xml"
           printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") > file}
    END   {printf("</notes>") > file}
    
  2. You shouldn't be doing the I/O redirection in the awk script in the first place. You should let the shell do the I/O redirection.

    awk '
    BEGIN {printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")}
    END   {printf("</notes>")}
    ' > notes.sasi89.xml
    

There are times when I/O redirection in the script is appropriate, but that's when you need output to multiple files. When, as appears very probable here, you have just one output file, make the script write to standard output and have the shell do the I/O redirection. It is much more flexible; you can rename the file more easily, and send the output to other programs via a pipe, etc, which is very much harder if you have the output file name embedded in the awk script.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278