Awk and Trac.ini

You'll notice I'm posting late again, for which I blame C.S. Lewis, and since he's dead he can't defend himself from this unfounded accusation completely serious and non-trivial explanation for my tardiness.

As for actually post, I work as a support guy for a Subversion hosting company. We also host Trac, so part of my job is occasionally setting up custom ticket fields for customers. This involves editing the trac.ini, a simple text file. This is fairly easy when you just have to modify one Trac instance, but every now and again I have to modify a couple of dozen files. I have tried this using sed before, but this is a prime example of the the "When all you've got is a hammer, every problem is a nail" fallacy. I'd been sort of interested in learning more about awk and this seemed like a prime opportunity to "learn by doing", and now I'll reinforce with "learning by teaching". So with out further ado here's my short script interspersed with an explanation of how it works, and a complete copy of the code at the bottom.

BEGIN { i = 0 }

The BEGIN section is a special section that is run once before processing the file, it can be used for setting variables, as I have done here. The i variable, a more descriptive name would have been good, stores the state of the script.

{
    if ( i == 0 ) { print }

The { starts the main awk script, which is run once for each line in the file being processed. This first line simply prints out the input line being examined if i equals zero, which it does in the initial state of the program.

    else 
    {
        if ( i == 1 ) {
            print "# Ticket Custom Section\n"
          
            i = 2 }

The next section is the else clause for the preceding if clause, which executes it's own if-else pair. The if clause executes if i equals one, which it does if we have just passed the "[ticket-custom]" line in the trac.ini file. This section prints out the required custom ticket definitions and changes i to two, which will prevent anything from being written until it gets to the end of the custom ticket section, see below. You need to change the print statement to print the the required ticket custom section of course; it might be more readable to use a series of individual statements rather than just one.

        else { if ( $0 ~ /\[.*\]/ ) { print ; i = 0 } }
    }

This next line is executed if i doesn't equal zero or one, meaning that we are currently in the custom field section. It's a single short if statement that checks if the line being processed ($0) matches (~) a regular expression, in this case /\[.*\]/. This will match any line that contains a "[" followed by a series of characters, followed by a "]"; basically a trac.ini section head. So if it finds the start of a new section in the file it will print it out, and then set i back to zero, which means it will just print out the rest of the lines in the file.

    if ( $0 == "[ticket-custom]" ) { i = 1 }
}

Then here's the final line which is a simple if that is run for each line in the file and checks if the line is the start of the custom field section ([ticket-custom]), and if so sets i to one; the result of which is show above.

Since the code is probably slightly unclear unless you can see the whole thing here it is:

BEGIN { i = 0 }
{
    if ( i == 0 ) { print }
    else 
    {
        if ( i == 1 ) {
            print "# Ticket Custom Section\n"
          
            i = 2 }
        else { if ( $0 ~ /\[.*\]/ ) { print ; i = 0 } }
    }
    
    if ( $0 == "[ticket-custom]" ) { i = 1 }
}
Categories: Computers, Howto, Linux, Scripting
Date: 2009-05-05 23:03:53, 15 years and 234 days ago

Leave reply

No html allowed in reply

Notify me of follow-up comments via email.