Here is yet another answer to this ancient and oft-asked question (for linux at least).

The standard advice is found in perlfaq5, on perlmonks, and elsewhere. Using Number::Format or a commify() sub works well, but isn't very convenient for modifying existing code that was written with printf. It seems unlikely that perl's printf will ever support %'d and friends (see printf(3), scroll to "Flag Characters").

However, almost any linux system has a /usr/bin/printf command with %' support. So, the simple definition

sub cprintf {system('/usr/bin/printf', @_)}
will let you use
cprintf("There are at least %'d ways to do it!\n", 42e6)
to print: There are at least 42,000,000 ways to do it!

For this to work, your LC_NUMERIC environment variable should be set to a locale that has a "thousands separator", such as en_US.UTF-8. It seems to work quite well, at least for simple cases. To modify existing code, just change your printf's to cprintf's and add apostrophe's to the formats as needed. Less work than wrapping each argument with a subroutine call and changing each format to %s. It also helps keep things clear and readable.

It's tempting to override the builtin printf, but that's not easy to do. The CORE documentation lists printf as a special keyword. (Playing with tied file-handles or other tricks might work, but doesn't seem worth it too me.)

On the other hand, if you want to auto-magically commify *all* your %d's, you could use:

sub cprintf { my($fmt)= shift; $fmt=~s/%(-?\d*)d/%'$1d/g; system('/usr/bin/printf', $fmt, @_) }
And then  cprintf("%d", 42e6) will print 42,000,000.

Of course, there are plenty of potential pitfalls to this simple approach, including:
  1. Every cprintf execs a new process. You probably don't want to call cprintf() 42,000,000 times.
  2. You can't use perl's %v format, and perl can't check for missing or extra args to cprintf like it does for printf.
  3. Runtime errors from /usr/bin/printf may be hard to catch or diagnose.
  4. To print to a file, you have to re-direct stdout. Commified printing to a string (sprintf) in this way would be tricky. Backtics invoke the shell, which would be fraught with danger. You'd need IPC::System::Simple or something similar.
  5. /usr/bin/printf has some unique features (some might be useful). See the gnu coreutils docs, or try 'info coreutils printf' ('man printf' isn't very complete).
PS: To emphasize the caution above about backticks, do not use  sub {system("/usr/bin/printf @_")} as your definition, since then system() might invoke a shell as well. For example,
system('/usr/bin/printf', 'Bash uses backtics for cmd substitution, eg: %s', '`ls *`')
will print
Bash uses backtics for cmd substitution, eg: `ls *`
This works because perl puts two strings into **argv and then directly execs /usr/bin/printf. But,
system( '/bin/printf "Bash uses backtics for cmd substitution, eg: %s" `ls *`' )
will do something quite different, since perl will pass the single string to a shell, which will then execute ls. Replace 'ls' with 'rm' (or, horrors, 'rm -rf') and you've got a disaster on your hands!

Happy Holidays, and best wishes for the new year!
-Jeff


In reply to Printing large numbers with commas to show thousands groups. by jnorden

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.