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

I have been frying my brain on a regex that tests a users input to an HTML Form of a dollar amount, like $50.00 and will check it for anything other than digits. What I need to end up with is allowing a good digit sequence to pass and sending a bad digit sequence to an error page telling the user to re-input the values.

Criteria is:
1. Value must be followed by 2 digits after the period.
2. Value must have at least one digit in front of the period.
3. either digit sequences on either side of the period can only have digits. No non-word characters like white space, $#@!%&*()-_+=~`:;"'}{]|\/?.(more than one period)<>, are allowed.
What I need to end up with is that no matter what the user puts in the form field, it will only accept *X.XX where *X. is any dollar amount and .XX is any cents amount.
$50.00 or 50.0.0 or 50 will not work, it has to be 50.00. 50 is just an example, I need to work with any dollar.cents amount.
This is what I have done so far, but I can't get it to work all the way.

$Amount =~ /-?(\d+)\.?(\d+)/; $intergerpart = $1; $decimalpart = $2; if ($lengthdecimal gt 2 || $Amount =~ /[^0-9]\.?[^0-9]/) { display_output($templatefile,); #HTML error file print <<EOF; #Continues Processing }
I feel I am so close but something is just not right and I can't figure it out.
I hope one of you wizards can help out.
TIA!

Replies are listed 'Best First'.
Re: Regex Dollar Amounts
by japhy (Canon) on Oct 19, 2001 at 07:16 UTC
    You want a regex like so:
    if ($amount =~ /^\d+\.\d\d$/) { # it's ok } else { # it's bad }
    It's really quite simple: the beginning of the string, one or more digits, a '.', two digits, and then the end of the string. I can't tell from your post whether or not you want to accept a leading - sign.

    _____________________________________________________
    Jeff[japhy]Pinyan: Perl, regex, and perl hacker.
    s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

      Thanks!
      That worked great! I just had to change the =~ to !=, my code didn't like
      Having the print <<EOF; before thedisplay_output($templatefile,);
      Thanks for your help, I appreciate it!
      Wes
Re: Regex Dollar Amounts
by andreychek (Parson) on Oct 19, 2001 at 07:22 UTC
    You certainly seem to be on the right track. One thing that immediatly sticks out is that you don't appear to be using strict. That might really help with small things as they show up, as would turning on warnings (-w).

    Another problem is that you put a question mark immediatly before the . in your regex. By doing that, the decimal point becomes optional, which doesn't appear to be what you want.

    Also, I'm not quite sure what "$lengthdecimal" is.. you're using it in your "if" statement, I'm not sure if it's a misspelling, or if it was simply defined earlier in your code.

    With these things in mind, I might try something like this:
    # Test to see if we got the expected input if($amount =~ m/^-?(\d+)\.(\d\d)$/) { my $integerpart = $1; my $decimalpart = $2; # Display template for correct input here } else { # Display template for error here }
    And just for fun -- another option you have is to do this test with JavaScript. More recent JavaScript versions support regexes. If you want to support older browsers, there are other ways to go about testing input. If you catch the error before if hits your server, it saves a tremendous amount of time, which makes your application faster, which makes your users happier :-)

    Good luck!
    -Eric
      Hi
      Thanks for the help!
      I messed up copying my code. Darn.
      Here it is again, done correctly.

      $Amount =~ /-?(\d+)\.?(\d+)/; $intergerpart = $1; $decimalpart = $2; $lengthdecimal = length($decimalpart); if ($lengthdecimal gt 2 || $Amount =~ /[^0-9]\.?[^0-9]/) { display_output($templatefile,); print <<EOF;

      Thanks for the help. I'll give your idea a try.
        Hi Again Eric
        I tried the line
        if($amount =~ m/^-?(\d+)\.(\d\d)$/)
        But this regex is forcing me to put a non digit character in place for it to be true
        If I use $50.00, c50.00, abcd50.00 and so on it will produce a true result and allow the user to pass.
        So here is what I did and it seems to be working
        if ($Amount !~ m/^-?(\d+)\.(\d\d)$/) { display_output($templatefile,);#error page print <<EOF;#good result, move on

        I had to change the =~ to !~ because it didn't like having
         print <<EOF; before the display_output($templatefile,);
        for some reason.
        But it looks like all is well in Dodge City now. Thanks!
        Wes
perldoc -q redux
by Fletch (Bishop) on Oct 19, 2001 at 07:45 UTC
    $ perldoc -q 'is a number' Found in /usr/lib/perl5/5.6.1/pod/perlfaq4.pod How do I determine whether a scalar is a number/whole/integer/float? ...

    Not to mention `is a number' in the search box up above turns up gobs of hits.