Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

Re: Tweak for my Perl Regex that screens for digits only

by radiantmatrix (Parson)
on Jan 27, 2006 at 18:37 UTC ( [id://526046]=note: print w/replies, xml ) Need Help??


in reply to Tweak for my Perl Regex that screens for digits only

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

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://526046]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (2)
As of 2024-04-19 21:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found