in reply to Simple formatting question for credit card number

As not all credit card numbers have exactly 16 digits, the best thing to do is to build the spacing in reverse.
sub format_cc_num { my ($num, $spacer) = @_; $num = reverse $num; $num =~ s/(.{4})/${1}${spacer}/g; return reverse $num; }

------
We are the carpenters and bricklayers of the Information Age.

The idea is a little like C++ templates, except not quite so brain-meltingly complicated. -- TheDamian, Exegesis 6

Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

Replies are listed 'Best First'.
Re^2: Simple formatting question for credit card number
by Aristotle (Chancellor) on Aug 13, 2003 at 01:04 UTC
    Careful. Context will trip you up when playing with reverse. ++ otherwise.
    return scalar reverse $num;
    Why does everyone reach for substitution though?
    sub format_cc_num { my ($num, $spacer) = @_; scalar reverse join $spacer, (reverse $num) =~ /(....)/g; }

    Makeshifts last the longest.

      Actually, we both were buggy. Using your code and my code (with the appropriate bugfix), we have:
      #!/usr/bin/perl use strict; use warnings; my $x = "12345678"; my $y = "123456789"; sub dragonchild { my ($n, $s) = @_; $n = reverse $n; # Added negative lookahead $n =~ s/(.{4})(?!$)/${1}${s}/g; scalar reverse $n; } sub aristotle { my ($n, $s) = @_; scalar reverse join $s, (reverse $n) =~ /(....)/g; } foreach my $v ($x, $y) { print dragonchild($v, '-'), $/; print aristotle($v, '-'), $/; } ------ 1234-5678 1234-5678 1-2345-6789 2345-6789

      Your code only works for card numbers that are a multiple of 4. Most department store cards are 11 digits and some, like AmEx, are moving to 17 or 19 digits. (I used to work for MC ... we had a similar function that I had to maintain in the app I worked on. It was written horribly with substr and the like.)

      ------
      We are the carpenters and bricklayers of the Information Age.

      The idea is a little like C++ templates, except not quite so brain-meltingly complicated. -- TheDamian, Exegesis 6

      Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

        Oops. I was going to use unpack at first and didn't think about that when going for the pattern instead. The fix is obvious, though.
        sub format_cc { my ($n, $s) = @_; scalar reverse join $s, (reverse $n) =~ /(.{1,4})/g; }

        Makeshifts last the longest.