Perl can use the thousands separator appropriate for your locale, as well as the appropriate decimal separator. The Number::Format from CPAN can do all sorts of interesting localizations, but POSIX can do it.
I debated offering an example in Learning Perl (7th Edition), but POSIX‘s localeconv
function returns a hash reference. And, although I’ve added an appendix covering experimental features, I didn’t want to go through enough Perl to explain slices and postfix dereferencing.
Before I get to the Perl, there are a few tips. The locale
command with no arguments shows you what you have set so far:
$ locale LANG="en_US.UTF-8" LC_COLLATE="de_DE.UTF-8" LC_CTYPE="de_DE.UTF-8" LC_MESSAGES="de_DE.UTF-8" LC_MONETARY="de_DE.UTF-8" LC_NUMERIC="de_DE.UTF-8" LC_TIME="de_DE.UTF-8" LC_ALL="de_DE.UTF-8"
The locale
command with -a
shows you what you have installed on your system. The locale is really groups of files (maybe in /usr/share/locale) that have settings for various things, such as the monetary thousands and decimal separators.
I can get these settings POSIX‘s localeconv
, which returns a hash reference. Note that if you haven’t completely set your locale, some of the keys may be missing.
use v5.22; use feature qw(postderef); no warnings qw(experimental); use POSIX qw(locale_h); # returns a hash reference, which we don't cover in Learning Perl # LC_NUMERIC should be set. For instance: # % export LC_ALL=de_DE.UTF-8 my $hash = localeconv(); # Reading about locales can help # http://lh.2xlibre.net/locales/ my( $thousands, $decimal ) = $hash->@{qw(mon_thousands_sep mon_decimal_point)}; # set some defaults if the locale did not set them $thousands //= ','; $decimal //= '.'; # treat the number as a string my $number = join $decimal, 123456789, 1234; 1 while ($number =~ s/^(-?\d+)(\d\d\d)/$1$thousands$2/); say "Number is $number";
When I run this under different locales, the output is a bit different:
$ LC_ALL=en_US.UTF-8 perl5.22.0 test.pl Number is 123,456,789.1234 $ LC_ALL=de_DE.UTF-8 perl5.22.0 test.pl Number is 123.456.789,1234
Be careful – not all locals separate every three digits. For instance, India (at least English language locales there). There, 1,000,000 is apparently written 10,00,000 .
Fortunately, CPAN can help. 🙂 See CLDR::Number
#!/usr/bin/env perl
use v5.10;
use CLDR::Number;
my $cldr = CLDR::Number->new(locale => 'en-in');
my $decf = $cldr->decimal_formatter;
say $decf->format(1_000_000);
perl:~$ perl test.pl
10,00,000