It seems like you are looking for a generalized way to allow certain groups of characters (primarily), with an addition to allow certain strings.

First, think about which chars you'd like to allow. Since this is a phone number, these are spaces, digits, hyphens, parentheses, and periods (dots). The key here is that this is the class of chars you'd like to allow. So, to check if a form has only these chars

# true if $string consists solely of allowed chars (and isn't empty) $string =~ m/^[\s\d-\(\)\.]+$/; # or, we could be true if $string contains anything except allowed cha +rs $string =~ m/[^\s\d-\(\)\.]/;

The second approach uses the char-class negation -- the regex will be true if it finds at least one char not in the set. I like this approach less, so the remainder of examples will follow the other pattern (true if "good").

Your next step is to deal with how people might specifiy extentions. The forms I have seen are "x1234", variations on "ext. 1234", and "(1234)". The last is already addressed in the regex we have, because it uses all legal chars. We address the first option ("x1234") by adding 'x' as a legal char in our class. We then deal with the ways we can allow the "ext. 1234" style by checking for the forms of "ext." (I choose to allow "ext" and "Ext" with an optional period.

$string =~ m/^[\s\d-\(\)\.x]+|(?:[Ee]xt[\.]*)*$/;

Now, that's fairly complex and somewhat hard to understand if you don't already grok regex. It's also easy to make a mistake maintaining it. Here's an alternate approach:

sub is_valid { # check to see if an entry consists of valid "phone number" chars. my ($phone) = @_; $phone =~ s/[\-\.\s\(\)]+//g; #remove punct. and spaces # return 1 if begins with digits and is followed by # Ext or ext or x and digits. return ( $phone =~ m/^\d+(?:(?:[Ee]xt)|x)*\d$/ ); }

By removing spaces and punctuation, we've made our task a little easier: we can validate that something has all legal chars, and do a minimal level of format checking as well (e.g. extentions must be at the end, if provided; everything begins and ends with digits {not counting puctuation}, etc.).

This might be used like:

unless ( is_valid($FORM{'phone'} ) { send_error("$FORM{'phone'} doesn't meet validity test"); exit; }

If readability isn't a concern (but really, when isn't it?), you could combine the ideas into a complex regex:

$phone =~ m{^\d+[\d\-\.\s\(\)]+(?:(?:[Ee]xt[\.]*)|x)*\d$};

All said, you might find it easier to alter your entire approach, creating an HTML form that has two fields, 'phone' and 'ext', then checking that the 'phone' is all digits and punctuation and the ext is all digits (or empty). Like this:

# valid number unless ($FORM{'phone'} =~ /^\d+[\s\d-\(\)\.]+$/) { die "Bad phone"; } #valid ext, if it exists unless ($FORM{'ext'} =~ /^\d+$/) { # don't die if zero-length! die "Bad ext" if length($FORM{'ext'}); }

These regexen and code snippets are untested, and so might have some problems. Not nearly enough coffee today -- don't say I didn't warn you!

<-radiant.matrix->
A collection of thoughts and links from the minds of geeks
The Code that can be seen is not the true Code
I haven't found a problem yet that can't be solved by a well-placed trebuchet

In reply to Re: Tweak for my Perl Regex that screens for digits only by radiantmatrix
in thread Tweak for my Perl Regex that screens for digits only by hackermike

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.