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

I'd like to have a regex to evaluate whether a user has entered a valid string. Valid strings are a comma delimited set of four digit numbers i.e 9500,9501,9502

I'd like to be able to know if a user has entered anything not confirming to that pattern i.e 9500,goats,9501 or 9500,,,,,,,,, that kind of thing.

Here's what I've got so far, it kinda sorta works but doesn't capture everything. Could anyone off any suggestions?

my $string = '9500,9501'; if ($string =~ /^[\d{4}\,]+$/) { print "Looks ok\n"; }else { print "Not ok\n"; }

Replies are listed 'Best First'.
Re: Validating Comma Delimited String
by moritz (Cardinal) on Jan 08, 2009 at 23:31 UTC
    You can't have a dynamic number of captures in Perl 5 (except perhaps with very evil hacks), so you shouldn't even try to. If you want to work with the data, split it on the comma.

    For validation, just use m/^\d{4}(?:,\d{4})*$/ (assuming that one four-digit number always has to be present).

Re: Validating Comma Delimited String
by gone2015 (Deacon) on Jan 08, 2009 at 23:37 UTC
      $string =~ /^\d{4}(?:\,\d{4})*$/

    ... start, 4 digits, then any number of comma followed by 4 digits up to end (and then stop).

    ... and having validated, then you can split(/,/, $string) to "capture" the numbers.

Re: Validating Comma Delimited String
by zwon (Abbot) on Jan 08, 2009 at 23:32 UTC
    /^\d\d\d\d(,\d\d\d\d)*$/
Re: Validating Comma Delimited String
by Bloodnok (Vicar) on Jan 09, 2009 at 11:44 UTC
    As Corion points out, you can't have a variable number of captures, but as you don't ask about/mention it explicitly, that probably isn't a problem ;-)

    More of a problem, however, is your use of a range ([...]) c/w a block/capture ((...)). Try ...

    perl -we '$string = qq/9500,9501,fred,,9999/; map { warn qq/Bad entry: + $_ in string $string/ } grep ! /^\d{4}$/, split /,/, $string;'
    Gives
    Bad entry: fred in string 9500,9501,fred,,9999 at -e line 1. Bad entry: in string 9500,9501,fred,,9999 at -e line 1.

    A user level that continues to overstate my experience :-))