tags:

views:

63

answers:

4

I have form where user submits field. Field can have letters, numbers, and punctuation. But I want to check to make sure that at least 3 of the characters are letters. How can I regex that?

For example,

$string = "ab'c";

And I need something like,

if (preg_match("/[a-z]{3}/i", $string))
    print "true";
else
    print "false";

That string has three letters, even though it has an apostrophe. It should test true. But for some reason, that tests false right now.

Any help?

A: 

Try this: The $ matches the end of the string ;)

if (preg_match("/[a-zA-Z\']{3}$/i", $string))
    print "true";
else
    print "false"; 

Edit: Sorry, I misunderstood your question. Try this:
^([a-zA-Z\']{3,}(.?))$

Results:
hell'o <-- true
h31l0 <-- false
hello <-- true

Daan
I want it to test true if there are at least 3 letters. So all those cases of hell0 I would like to test true.
codemonkey613
? All you've done is sustitute both upper and lower for the original lower (which I'm pretty sure is already handled by the "/i" anyway). In any case, both "hell'o" and ""hell0" _satisfy_ the conditions.
paxdiablo
@paxdiablo : No, i added the $ sign to match the end of the string.@codemonkey: Oh, I think I mis understood your question, I thought you wanted to match 3 alphanumeric chars at the end of the string... Sorry for that.
Daan
+1  A: 

You cannot write a regexp that checks for "at least x symbols of a class". Of course you can

preg_match_all('~([a-z][^a-z]*){3}~', "ab'c")

In more complex cases, you can replace the class to something else and then compare results (or simply use preg_replace fourth parameter):

preg_replace('~[a-z]~', '', "ab'c", -1, $count);
print_r($count); // prints "3"
stereofrog
Err, yes you can :-)
paxdiablo
Yeah, I thought of that a second ago. I can strip everything except letters, and then check string length to see if it's more than 3. Thanks.
codemonkey613
+1  A: 

Try this regular expression:

^([0-9,]*[A-Za-z]){3}[A-Za-z0-9,]*$

You could also remove all non-letter characters and check the length:

if (strlen(preg_replace('/[^A-Za-z]+/', '', $str)) >= 3) {
    // $str contains at least three letters
}
Gumbo
Yep, that works too. Thanks!
codemonkey613
+2  A: 

How about a case insensitive match on:

([a-z][^a-z]*){3}

Looks for 3 groups of a letter, and any number of non letters.

Mike Boers
I think we have a winner! :D Thanks so much.
codemonkey613
Might be slightly more efficient to make the `*` non-greedy... *shrugs*.
Mike Boers
@Mike: If performance mattered, a non-greedy quantifier would probably make thinks worse, not better. A *possessive* one would definitely be more efficient -- `([a-z][^a-z]*+){3}` -- but we're talking about validating user input, so performance is not a legitimate concern.
Alan Moore