meonkeys has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to match 1234.12, 1234, .12, and 0.12, but not .123 or .1234. Any suggestions?

This is the best I could come up with (but it doesn't work...)
($test =~ /\$?\d+\.?/ && $test !~ /\.\d{,2}/)

Note: I know I could/should be using Math::Currency, but this is more a regex question than a currency formatting question.

Replies are listed 'Best First'.
Re: Money Regex
by AgentM (Curate) on Feb 05, 2001 at 12:08 UTC
    Correct me if I'm wrong, but after looking at your example cases, i would most likely suggest:
    use POSIX; ... crashNburn() if (floor($cash*100) != $cash*100);

    AgentM Systems nor Nasca Enterprises nor Bone::Easy nor Macperl is responsible for the comments made by AgentM. Remember, you can build any logical system with NOR.
      This can fail depending on how $cash*100 rounds
      If your processor uses ANSI/IEEE 754-1985 floating point numbers, try floor(100*1.14)
        Except that there shouldn't be anything there to affect the rounding. Everything greater than the hundreth place should be zero as described in the examples.
        AgentM Systems nor Nasca Enterprises nor Bone::Easy nor Macperl is responsible for the comments made by AgentM. Remember, you can build any logical system with NOR.
Re: Money Regex
by the_slycer (Chaplain) on Feb 05, 2001 at 12:04 UTC
    This is what I came up with..
    /^\$?(\d+)?\.?\d?\d?$/
    Basically, just matches the start of the string followed by an optional dollar sign, followed by one or more optional numbers, followed by an optional period followed by 2 optional numbers. Followed by the end of the string

    But, I am by no means a regex expert, this seems to work, I have tested against a file containing lines with letters and numbers, as well as criteria above, but I am sure someone else will point out the glaring errors in the above :-)
      I'd just change it a little bit:

      /^\$?\d+(\.\d\d)?$/

      That matches $12, $12.00, $0.12, etc.., but not $12., $.50, $12.013, etc..

      Regards, octopus
      --
      GED/CC d-- s:- a--- C++(+++) UL+++ P++++$ L++>++++ E--- W+++@ N o? K? w-- O- M-(+) V? !PS !PE !Y PGP+(++) t-- 5 X+ R+(+++) tv+(++) b++@ DI+() D+ G++ e->+++ h!++ r+(++) y+
      Uh, as long as you have no problem with it matching "" and "$" and "." that regex will do just fine. If you make everything in a regex optional, you aren't going to get what you really meant very often.

      I'd start with /^\$?(\d+(\.\d{1,2})?|\.\d{1,2})$/ which requires there to be at least one digit before an optional decimal and 1 or 2 digits or that there be a decimal followed by 1 or 2 digits. It is ugly but it works.

      --
      $you = new YOU;
      honk() if $you->love(perl)

Re: Money Regex
by meonkeys (Chaplain) on Feb 05, 2001 at 12:00 UTC
    duh. I guess this would work.
    ($test =~ /^(\$?\d+(\.\d{0,2})?|\$?\.\d{1,2})$/)

    Please ignore my mental mastication (this thread).
Re: Money Regex
by Fastolfe (Vicar) on Feb 06, 2001 at 00:04 UTC
    You're also neglecting stuff like 12.. Here are a few steps to getting a regex like you want:
    /^\d+$/ # integer /^\d+(?:\.\d+)?$/ # integer or optional real /^\d+(?:\.\d\d)?$/ # int or opt. 2-digit float /^\d+(?:\.(?:\d\d)?)?$/ # int, int with opt '.', or 2-digit float # Ways of doing optional integer portion (e.g. .12) /^\d*(?:\.(?:\d\d)?)?$/ # WRONG (matches "") /^\d+(?:\.(?:\d\d)?)?$|^\.\d\d$/ # better, but still ugly
    Forget about doing gas prices with a regex like this, though (e.g. 1.499). Don't forget about negative-signs also, if that's necessary.

    I also haven't tested any of that.

Re: Money Regex
by jynx (Priest) on Feb 05, 2001 at 23:05 UTC

    Since you don't really need to know what the exact sides are, why not let perl do most of this for you?
    use strict; use Carp; my ($l, $r, @err) = split /\./, $test; carp "oops, more than 2 \.'s.\n" if @err; if ($l) { if ($r) { #handle case of rational dollars } else { #handle case of integer dollars } } else { carp "oops, we don't even have a dollar!\n"; }
    This seems like it'll cover more cases than you currently have (never trust your user) and it seems a bit easier as well...

    HTH,
    jynx


    ps if another monk can spot errors please do so, it's early and i haven't had my coffee yet...