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

I have a small script that makes a quick frequency list of words from a few text files. Output example:
word 12 longerword 1 evenlongerwordthantheonebefore 2
I was wondering if it’s possible to use printf to always print the frequency at a designated place like:
word 12 longerword 1 evenlongerwordthantheonebefore 2
This would be the line the print happens in;
printf "%s %5d\n", $word, $seen{$word}; #word frequency
Any tips?

Replies are listed 'Best First'.
Re: printf question
by almut (Canon) on Jan 21, 2010 at 10:49 UTC

    Sure. Something like this

    printf "%-33s %d\n", $word, $seen{$word};

    The 33 sets the width of the field, and the minus sign left-aligns the content in it.

      almut's right.

      You can get a slight improvement by keeping track of your longest word as you count them, though, and then using printf's "*" modifier to read the field width from that variable.

      printf "%-*s %d\n", $maxLen, $word, $seen{$word};
      I'd put a width specifier on the %d so the numbers line up nicely as well, but that's just my preference:
      printf "%-*s %4d\n", $maxLen, $word, $seen{$word};

      Mike
      Thank you good Sir!
Re: printf question
by roboticus (Chancellor) on Jan 21, 2010 at 11:36 UTC

    peokai:

    You can answer questions like this simply by reading the documentation. The perldoc command makes it pretty easy to find information on standard perl functions using the command "perldoc -f functionName". For example, the documentation on printf would have pointed you to the answer:

    [06:28]$ perldoc -f printf printf FILEHANDLE FORMAT, LIST printf FORMAT, LIST Equivalent to "print FILEHANDLE sprintf(FORMAT, LIST)", + except that "$\" (the output record separator) is not appended +. The first argument of the list will be interpreted as the " +printf" format. See "sprintf" for an explanation of the format argument. If "use locale" is in effect, and POSIX::set +locale() has been called, the character used for the decimal sep +arator in formatted floating point numbers is affected by the LC_NUMERIC locale. See perllocale and POSIX. Don’t fall into the trap of using a "printf" when a sim +ple "print" would do. The "print" is more efficient and le +ss error prone. [06:28]$ perldoc -f sprintf sprintf FORMAT, LIST Returns a string formatted by the usual "printf" conven +tions of the C library function "sprintf". See below for more d +etails and see sprintf(3) or printf(3) on your system for an explanation of the general principles. For example: # Format number with up to 8 leading zeroes $result = sprintf("%08d", $number); <<<quite a bit of text snipped out>>> (minimum) width Arguments are usually formatted to be only as wide +as required to display the given value. You can overri +de the width by putting a number here, or get the width fr +om the next argument (with "*") or from a specified argume +nt (with e.g. "*2$"): printf '<%s>', "a"; # prints "<a>" printf '<%6s>', "a"; # prints "< a>" printf '<%*s>', 6, "a"; # prints "< a>" printf '<%*2$s>', "a", 6; # prints "< a>" printf '<%2s>', "long"; # prints "<long>" (does + not truncate) If a field width obtained through "*" is negative, +it has the same effect as the "&#8722;" flag: left-justifi +cation.

    An added benefit of reading the documentation would be that you'd learn quite a bit more about printf/sprintf, which couldn't hurt. If you want to look over all the standard functions (which I do every now and then) you can use "perldoc perlfunc". Be sure to explore all the documentation to find out what's out there so you can answer things yourself.

    ...roboticus

Re: printf question
by toolic (Bishop) on Jan 21, 2010 at 13:41 UTC
    An alternative to printf is Text::Table, which automatically calculates the width of each column for you. So, if all you want is basic tabular output, and you really don't care if column 1 is 27 wide, or 36 wide, just let Text::Table do the work for you.
Re: printf question
by graff (Chancellor) on Jan 22, 2010 at 03:11 UTC
    Now that you know everything you need about (s)printf, I would just ask you: why not put the numbers in the first column? If your (s)printf formatting was like this:
    printf( "%5d %s\n", $seen{$word}, $word );
    you wouldn't have to worry about how big the words are. (You only have to worry about how big the numbers get, and that's a much easier issue to handle.)
maybe format is what you want
by doug (Pilgrim) on Jan 21, 2010 at 18:21 UTC

    If all you want is columns of output like that, read the perlform page and learn about formats. format an old and rigid interface, but it might be a good match for what you want.