great regex! me too have forgoten about the look-ahead assertion :(
my function that does number beautifying has no less than 8 lines :((
still.. there's a little problem when handling floats:
the digits after the dot shouldn't be 'beautified' :(
.. i tried to enhance a little your line but the problem still remains because of the fixed-width look-behind:
$number =~ s/(?<!\.\d)(\d)(?=(\d{3})+(\D|$))/$1,/g;
(this example works for numbers with 5 digits after the dot... variations may me done by modifying the 'quantity' of \d from the look-behind assertion)
couldn't think at anything better now.. maybe you have another bright idea for this too o=)
so, after inserting your wizcraft, my lame tool looks something like this:
$number =~ s/(\d+)(\.\d+)?/bea_int($1).$2/eg;
sub bea_int {
my $kk = $_[0];
$kk =~ s/(\d)(?=(\d{3})+(\D|$))/$1\,/g;
return $kk;
}
--
AltBlue... w8ing 4 a better solution o=Q | [reply] [Watch: Dir/Any] [d/l] [select] |
The easy way to deal with open ended floating pointed nums is to simply remove the floating part until the commas are added, then reattach.
$integer =~ s/(.*)(\.\d\d+)$/$1/;
$float = $2;
# do stuff
$integer .= $float;
| [reply] [Watch: Dir/Any] [d/l] |
lol. isn't that what i'm currently doing ?! :))
plz check up again my previous post and look at the final code - it does exactly that :)
your snippet doesn't work for 'real' strings like:
'for every 1234.567 blah stuff there is some 34% rate of foobar success at every 9876543.876543 seconds'
--
AltBlue.
| [reply] [Watch: Dir/Any] |
It would be more efficient to use split.
my( $int, $float ) = split /\./, $num;
| [reply] [Watch: Dir/Any] [d/l] |
This regex continues adding commas after a decimal point if there are at least 4 decimal places. It also does repeated lookahead checks for multiples of 3 digits. I came up with a better regex using a single lookahead for the multiple of 3 digits and using \G to stay in sync thereafter, and not continuing past a decimal point. Here's what I ended up with:
$number =~ s/(^\D*\d{1,3}(?=(?:\d{3})+)(?!\d))|\G\d{3}(?=\d))/$1,/g;
For example, "12345678.9012345" becomes "12,345,678.9012345" instead of "12,345,678.9,012,345". Of course, after I came up with this, I saw the current perlfaq5 and saw an extremely similar example there from Benjamin Goldberg:
s/(^[-+]?\d+?(?=(?>(?:\d{3})+)(?!\d))|\G\d{3}(?=\d))/$1,/g;
Oh well, I guess it wasn't a new idea after all! His version adds the (?>...) non-backtracking construct, which is definitely an improvement over mine. He only matched a sign at the beginning, which is reasonable. I had [+-]? at one point, but it occurred to me that a monetary value might already have a dollar sign prefixed to the number, so I used \D* instead. I think it's a wash to use \d+? instead of \d{1,3} as I had -- it prefers checking for 1 digit first instead of 3 digits, but there's no way to know which of the 3 will match. If I changed mine to \d{1,3}? then it would be functionally equivalent. | [reply] [Watch: Dir/Any] [d/l] [select] |
Thanks for the insight. I'm ignorant of the secrets of lookahead,
lookbehind, inner repetitions, and all the other associated
voodoo with things like this, so while this regex certainly
works, the breakdown of what it all means is a mystery to
me. Would "Mastering Regular Expressions" be a good
teacher for this sort of thing?
Thanks, merlyn (++), and everybody else for their help and insight. | [reply] [Watch: Dir/Any] |
The currently available Mastering Regular Expressions doesn't cover any of the really cool Perl 5 regex stuff. Jeffrey Friedl is in the process of rewriting
the book for a second edition, and has been working with the Perl developers to
uncover inconsistencies in the implementation (what normal people would
call "bugs" {grin}) and gaps in the documentation.
Don't hold your breath though. I know this effort will probably take one to two
years of nights and weekends. "Been there Done that" x $n
-- Randal L. Schwartz, Perl hacker
| [reply] [Watch: Dir/Any] |