nysus has asked for the wisdom of the Perl Monks concerning the following question:

I've never been able figure out how to properly use printf. I've got the following line of code:
printf %s18 %s18 %s18, ($ip_date_time[$i]{ip}, $ip_date_time[$i]{date} +, $ip_date_time[$i]{time}, "\n");
which, in case you can't tell, is trying to print out three columns, one for each field, with a minimum width of 18. I just get some weird errors. The perldoc on sprintf and printf seems just about useless unless you are familiar with Cs sprintf function. Can someone point me to a tutorial on this function?

$PM = "Perl Monk's";
$MCF = "Most Clueless Friar Abbot";
$nysus = $PM . $MCF;
Click here if you love Perl Monks

Replies are listed 'Best First'.
Re: Using printf
by busunsl (Vicar) on Jul 02, 2001 at 14:34 UTC
    I don't know a tutorial, just the man-pages.

    But here comes a short explanation:

    printf take a pattern string and a list of value, to fill into the pattern.
    So the basic form is:

    printf "pattern", value, value, value;

    This pattern can hold any kind of text, including newlines, if you put it between doubles.
    The pattern contains a placeholder for each value in the list.

    The placeholders look like %n.mt, where the % is the begin of the placeholder, n is the length, m is the decimals if you have a number and t is the type of value.

    n and m are optional, t can be one of a long list of which are s,d,f some examples.
    s is for strings, d is for integers and f is for floats.
    The complete list and further info can be found here

    Transforming your example to this gives:

    printf "%18s %18s %18s\n", $ip_date_time[$i]{ip}, $ip_date_time[$i]{date}, $ip_date_time[$i]{time};

    update: added link to perlfunc:sprintf

    update 2:there is a tutorial in the tutorial section (where else :-): Using (s)printf()

Re: Using printf
by $code or die (Deacon) on Jul 02, 2001 at 14:27 UTC
    Hi nysus, Your format needs to be quoted, also your digits need to be between the % and the s...
    printf "%18s %18s %18s", ($ip_date_time[$i]{ip}, $ip_date_time[$i]{dat +e}, $ip_date_time[$i]{time});
    Also, your "\n" won't get printed since your format has 3 "slots" and you are passing it 4 parameters. You can put the "\n" in the format.

    $ perldoc perldoc
Re: Using printf
by clemburg (Curate) on Jul 02, 2001 at 14:21 UTC

    Read Appendix A of Effective Perl Programming. (Or say "man 3 printf" in a Linux/Unix shell ... might also help.)

    Update: If you need to get the output into a text format (e.g., for redirecting into a file), do this (thanks to jmcnamara for the tip):

    man 3 printf | col -b > printf.txt

    The "col()" command will filter out all the terminal escapes for you.

    Update: Why "man 3 printf"? Because there is a printf command, too, and you will get its man page when you just say "man printf". But you want the manpage on the printf C library call, so you have to use "man 3 printf" to indicate you want the printf entry from section 3 of the manpages, which describes (surprise) library calls. See "man man" for more details on the surprisingly useful man command.

    Christian Lemburg
    Brainbench MVP for Perl
    http://www.brainbench.com

      And if you want to print out a nice troff formatted version of a man page (looks great on most printers), you can use the nifty -t switch:

      man -t printf | lpr

      (You need troff installed, but that should be there on any *nix-like OS worth having =)

      perl -e 'print "How sweet does a rose smell? "; chomp ($n = <STDIN>); +$rose = "smells sweet to degree $n"; *other_name = *rose; print "$oth +er_name\n"'
(bwana147) Using printf
by bwana147 (Pilgrim) on Jul 02, 2001 at 18:32 UTC

    Other mighty monks have already said all that there is to say. I'll just add some comments about legibility and nice formatting.

    The printf function takes a format as first argument, and then a list of values. The first argument being special, I'm fond of using the => operator to let it stand out from the rest:

    printf "%18s %18s %18s\n" => $ip_date_time[$i]{ip}, $ip_date_time[$i]{date}, $ip_date_time[$i]{time};

    Now, we use three times the $ip_data_time[$i]: if you translate that into English, it reads: "print out the ip of the ith element of $ip_date_time, the date of the ith element of $ip_date_time and the time of the ith element of $ip_date_time". I guess it would sound more natural to say "print out the ip, date and time of the ith element of $ip_date_time". Several ways to say that in perl:

    # a map print "%18s %18s %18s\n" => map {$ip_date_time[$i]{$_}} qw/ip date tim +e/; # a hash slice print "%18s %18s %18s\n" => @{$ip_date_time[$i]}{qw/ip date time/};

    Voilà, that was just my €0.02.

    --bwana147

Perl w/o C
by petdance (Parson) on Jul 02, 2001 at 18:38 UTC
    I'm having a bit of an eye-opening here. It never occurred to me that a monk might have never had to write in C before.

    xoxo,
    Andy
    --
    Throw down the gun and tiara and come out of the float!