Perl Programming Page 2 - Templating Tools |
Formats have been in Perl since version 1.0. They're not used very much these days, but for a lot of what people want from text formatting, they're precisely the right thing. Perl formats allow you to draw up a picture of the data you want to output, and then paint the data into the format. For instance, in a recent application, I needed to display a set of IDs, dates, email addresses, and email subjects with one line per mail. If we assume that the line is fixed at 80 columns, we may need to truncate some of those fields and pad others to wider than their natural width. In pure Perl, there are basically three ways to get this sort of formatted output. There's sprintf (or printf) and substr: for (@mails) { Then there's pack, which everyone forgets about (and which doesn't give as much control over truncation): for (@mails) { And then there's the format: format STDOUT = for (@mails) { Personally, I think this is much neater and more intuitive than the other two solutions--and has the bonus that it takes the formatting away from the main loop, making the code less cluttered.* Formats are associated with a particular filehandle; as you can see from the example, we've determined that this format should apply to anything we write on standard output. The picture language of formats is pretty simple: fields begin with @ or ^ and are followed by <, |, or > characters specifying left, center, and right justified respectively. After each line of fields comes a line of expressions that fill those fields, one expression for each field. If we like, we could change the format to multiple lines of fields and expressions: format STDOUT = We've seen examples of the @-type field. If you're dealing with multi-line formats, you might find that you want to break up a value and show it across several lines of the format. For instance, to display the start of an email alongside metadata about it:
This is where the other type of field, the ^ field, comes in: you can achieve the preceding output by using a format like this: format STDOUT = Id : @<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $_->id $message Date : @<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $_->received $message From : @<<<<<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $_->from_address $message Subject : @<<<<<<<<<<<<<<<<<<<<... ^<<<<<<<<<<<<<<<<<<<<<<<<<<<... $_->subject $message Unlike the values supplied to an @ field, which can be any Perl expression, these ^ values must take an ordinary scalar. What happens is that each time the format processor sees a ^ field, it outputs as much as it can from the supplied value and then chops that much off the beginning of the value for the next iteration. The ... sign at the end of the field indicates that if the supplied value is too long, the format should truncate the value and show three dots instead. If you use ^ fields with values found in lexical variables, such as $message in the previous example, you need to declare the lexical variable before the format, or else it won't be able to see the variable. Another boon of using formats is that you can set a header to be sent out at the top of each page--Perl keeps track of how many lines have been printed by a format so it knows when to send out the next page. The header for a particular filehandle is a format named with _TOP appended to the filehandle's name. The simple use of this is to give column headers to your one-line records: format STDOUT_TOP = format STDOUT = Formats are quite handy, especially as you can associate different formats with different filehandles and send data out to multiple locations in different ways. On the other hand, they have some serious shortcomings that you should bear in mind if you're thinking of using them in a bigger application. First, they're a camping ground for obscure special variables: $% is the current format page number, $= is the number of printable lines per page, $- is the number of lines currently left on the page, $~ is the name of the current output format, $^ is the name of the current header format, and so on. I could not remember a single one of these variables and had to look them up in perlvar. Formats also deal pretty badly with lexical variables, changing filehandles, variable-length lines, changing formats on the fly, and so on. But they're handy for neat little hacks.
blog comments powered by Disqus | |||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
|
|
|