Приглашаем посетить
Ходасевич (hodasevich.lit-info.ru)

Section 5.5.  Formatted Output with printf

Previous
Table of Contents
Next

5.5. Formatted Output with printf

You may wish to have a little more control with your output than print provides. In fact, you may be accustomed to the formatted output of C's printf function. Fear notPerl provides a comparable operation with the same name.

The printf operator takes a format string followed by a list of things to print. The format[*] string is a fill-in-the-blanks template showing the desired form of the output:

[*] Here, we're using "format" in the generic sense. Perl has a report-generating feature called "formats" that we won't even be mentioning (except in this footnote) until Appendix B, and then only to say that we really aren't going to talk about them. So, you're on your own there. Just wanted to keep you from getting lost.

    printf "Hello, %s; your password expires in %d days!\n",
      $user, $days_to_die;

The format string holds a number of so-called conversions; each conversion begins with a percent sign (%) and ends with a letter. (As we'll see in a moment, there may be significant extra characters between these two symbols.) There should be the same number of items in the following list as there are conversions; if these don't match up, it won't work correctly. The example above has two items and two conversions, so the output might look something like this:

    Hello, merlyn; your password expires in 3 days!

There are many possible printf conversions, so we'll take time here to describe the most common ones. Of course, the full details are available in the perlfunc manpage.

To print a number, generally use %g,[Section 5.5.  Formatted Output with printf] which automatically chooses floating-point, integer, or even exponential notation as needed:

[Section 5.5.  Formatted Output with printf] "General" numeric conversion. Or maybe a "Good conversion for this number" or "Guess what I want the output to look like."

    printf "%g %g %g\n", 5/2, 51/17, 51 ** 17;  # 2.5 3 1.0683e+29

The %d format means a decimal[Section 5.5.  Formatted Output with printf] integer, truncated as needed:

[Section 5.5.  Formatted Output with printf] There's also %x for hexadecimal and %o for octal, if you need those. But we say "decimal" here as a memory aid: %d for Decimal integer.

    printf "in %d days!\n", 17.85;  # in 17 days!

This is truncated, not rounded; we'll see how to round off a number in a moment.

In Perl, printf is most often used for columnar data since most formats accept a field width. If the data won't fit, the field will generally be expanded as needed:

    printf "%6d\n", 42;  # output like Section 5.5.  Formatted Output with printfSection 5.5.  Formatted Output with printfSection 5.5.  Formatted Output with printfSection 5.5.  Formatted Output with printf42 (the Section 5.5.  Formatted Output with printf symbol stands for a space)
    printf "%2d\n", 2e3 + 1.95;  # 2001

The %s conversion means a string, so it effectively interpolates the given value as a string but with a given field width:

    printf "%10s\n", "wilma";  # looks like Section 5.5.  Formatted Output with printfSection 5.5.  Formatted Output with printfSection 5.5.  Formatted Output with printfSection 5.5.  Formatted Output with printfSection 5.5.  Formatted Output with printfwilma

A negative field width is left-justified (in any of these conversions):

        printf "%-15s\n", "flintstone";  # looks like flintstoneSection 5.5.  Formatted Output with printfSection 5.5.  Formatted Output with printfSection 5.5.  Formatted Output with printfSection 5.5.  Formatted Output with printfSection 5.5.  Formatted Output with printf

The %f conversion (floating-point) rounds off its output as needed and lets you request a certain number of digits after the decimal point:

    printf "%12f\n", 6 * 7 + 2/3;    # looks like Section 5.5.  Formatted Output with printfSection 5.5.  Formatted Output with printfSection 5.5.  Formatted Output with printf42.666667
    printf "%12.3f\n", 6 * 7 + 2/3;  # looks like Section 5.5.  Formatted Output with printfSection 5.5.  Formatted Output with printfSection 5.5.  Formatted Output with printfSection 5.5.  Formatted Output with printfSection 5.5.  Formatted Output with printfSection 5.5.  Formatted Output with printf42.667
    printf "%12.0f\n", 6 * 7 + 2/3;  # looks like Section 5.5.  Formatted Output with printfSection 5.5.  Formatted Output with printfSection 5.5.  Formatted Output with printfSection 5.5.  Formatted Output with printfSection 5.5.  Formatted Output with printfSection 5.5.  Formatted Output with printfSection 5.5.  Formatted Output with printfSection 5.5.  Formatted Output with printfSection 5.5.  Formatted Output with printfSection 5.5.  Formatted Output with printf43

To print a real percent sign, use %%, which is special in that it uses no element from the list:[*]

[*] Maybe you thought you could put a backslash in front of the percent sign. Nice try, but no. The reason that won't work is that the format is an expression, and the expression "\%" means the one-character string '%'. Even if we had gotten a backslash into the format string, printf wouldn't know what to do with it. Besides, C programmers are used to printf working like this.

    printf "Monthly interest rate: %.2f%%\n",
      5.25/12;  # the value looks like "0.44%"

5.5.1. Arrays and printf

Generally, you won't use an array as an argument to printf. That's because an array may hold any number of items, and a given format string will work with only a certain fixed number of items: if there are three conversions in the format, there will have to be exactly three items.

But there's no reason you can't whip up a format string on the fly since it may be any expression. This can be tricky to get right, so it may be handy (especially when debugging) to store the format into a variable:

    my @items = qw( wilma dino pebbles );
    my $format = "The items are:\n" . ("%10s\n" x @items);
    ## print "the format is >>$format<<\n"; # for debugging
    printf $format, @items;

This uses the x operator (which we learned about in Chapter 2) to replicate the given string a number of times given by @items (which is being used in a scalar context). In this case, that's 3 since there are three items, so the resulting format string is the same as if we had written it as "The items are:\n%10s\n%10s\n%10s\n." And the output prints each item on its own line, right-justified in a ten-character column, under a heading line. Pretty cool, huh? But not cool enough, because you can even combine these:

    printf "The items are:\n".("%10s\n" x @items), @items;

Here we have @items being used once in a scalar context to get its length and once in a list context to get its contents. Context is important.

    Previous
    Table of Contents
    Next