#!/usr/bin/perl -w
use strict;
use Number::Format qw(:subs :vars);
$NEG_FORMAT = "x";
print format_picture(123456789012345, 'No-###-#####-#######');
__END__
Prints:
No-123-45678-9012345
Note: the above code generates a warning in the module but that is probably easily fixed.
--
John.
| [reply] [d/l] |
I like the basic idea, but your right, the implementation could use some work. First off, a couple minor changes to how your doing it now. First off, your API is poorly defined -- the only API you seem to have is "change symbol '#' on digits of number", but your code will change #, X, or x. You should either document that, or remove it. Consider that a template of '#XJ42-##', plus a number of 100, will format to 01J42-00, not 1XJ42-00. Also, there are some innefficencies that you could get around easily. You can accumulate results with $res = $symbol . $res, which avoids having to keep around that list. Since $_ is gaurneteed to be one character long in your test, you don't need the ^...$ anchors. Also, you should use eq, rather then regex matches, when you can get away with it, in general, as they are much faster. Replace /^([Xx]|#)$/ with (($_ eq '#') || ($_ eq 'X') || ($_ eq 'x')) (or just ($_ eq '#'), if you decided that X isn't neccessary). Even ignoring that point, is there a reason you wrote [Xx]|#, rather then [Xx#]?
Most importantly, you could avoid most of the work by using a s///e to do your matching and substution (the /e modifier means the right hand side is an expression, not a double-quoted string (e for execute). See perlop, under "regex quote-like operators".
$_=reverse $form;
s =~ s/#/pop @num || 0/e;
return reverse $_;
Hm. On an alternate route, you should be able to convert them to s?printf-style format strings.
Warning: Unless otherwise stated, code is untested. Do not use without understanding. Code is posted in the hopes it is useful, but without warranty. All copyrights are relinquished into the public domain unless otherwise stated. I am not an angel. I am capable of error, and err on a fairly regular basis. If I made a mistake, please let me know (such as by replying to this node).
| [reply] [d/l] [select] |
Thank you for your corrections. Yes, my function changes #, X and x because a template can be like thit 'DSF-###-####' and like that - 'XXX-XXXXXX-XXXX'<code>. <br>If number is <code>2345 and template is 'Ro-XXX-XXXXX-XXX'<code> result has to be <code>'Ro-000-00002-345'. I used regular expression for compactness of code.Thanks for interenting idea about /e modifier. I haven't known it. (I don't know a lot of things yet I think ;)) ). Michael
| [reply] [d/l] [select] |
You could also use unpack for this, preferably in conjuction with sprintf:
#!/usr/bin/perl -wl
use strict;
my $str = 123456789012345;
print join "-", "No", unpack("a3 a5 a7", $str);
# Or slightly more flexible:
# Zero pad the string to the required length
$str = sprintf "%015s", $str;
my $template = "###-#####-#######";
$template =~ s/-/ /g;
$template =~ s/(#+)/'a' . length $1/eg;
# Template is now "a3 a5 a7"
print join "-", "No", unpack($template, $str);
# You could even automate it a little more as follows:
my $digits;
$str = 12345;
$template = "###-#####-#######";
$digits = $template =~ tr/#//;
$template =~ s/-/ /g;
$template =~ s/(#+)/'a' . length $1/eg;
$str = sprintf "%0*s", $digits, $str;
print join "-", "No", unpack($template, $str);
__END__
Prints:
No-123-45678-9012345
No-123-45678-9012345
No-000-00000-0012345
Update: Added last example.
--
John.
| [reply] [d/l] |
From what I understand of your intentions, you want to:
- Pad a number (with zeroes) out to a given number of digits (printf and its sister sprintf are useful for this)
- Break the padded number up into sections (substr is made for slicing up strings)
- Reformat these sections according to your "template" (printf calls it a "format")
Here's one way to do it, step-by-step
#!/usr/bin/perl
use warnings;
use strict;
my $num = 34; #example number
my $padded_num = sprintf("%015d",$num); #Step 1: Pad the number
my $first = substr($padded_num, 0, 3); #Step 2: Break the padded numb
+er up
my $second = substr($padded_num, 3, 5);
my $third = substr($padded_num, 8, 7);
my $string = sprintf("NO-%s-%s-%s", $first, $second, $third); #Step 3:
+ Reformat the sections
print $string . "\n";
davis
Is this going out live?
No, Homer, very few cartoons are broadcast live - it's a terrible strain on the animator's wrist
| [reply] [d/l] |
Davis, thanks for your reply. Your way isn't suit for me because template isn't fixed. I can have any numbers of templates and they can be different. So, it's hard to define format for sprintf.
Michael
| [reply] |
Your may want to look into the perlform manual page.
It might not be hard to translate your formats to Perl
formats. But since you gave only a single example,
it may be hard.
Abigail | [reply] |