Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations dencom on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Regular Expression question??? 3

Status
Not open for further replies.

ericse

Programmer
Apr 19, 2007
32
US
Hi, I'm not posting to actually ask for code, but rather, can Perl handle "AND"s in regular expressions? Like... I want to test a pw to make sure it has at least 1 capital letter, 1 lower case letter and one non-alphanumeric letter... but this has to be done in a ONE line regular expresion... anyway, i can get it to work if the format remains the same.. i.e. the non-alpha numeric key is always at the end.. that's easy, but what if the position of each of the aforementioned characters are floating (ie changing places)? ... can perl do:

$var = 'Testuser1$%';

$var = /[A-Z]+ (in any position) AND [a-z]+ (in any posiition) AND \W+ (in any positiion)/;

any input would be greatly appreciated... this is for a config script that is read by an app.. the app accepts only 1 line regular expressions... if i had the abliity to use more than 1 line, this would be simple, however, i don't... help?
 
there has to be a better way, but this is all I could think of:


Code:
/^[A-Z].*[a-z0-9].*\W.*$|^[A-Z].*\W.*[a-z0-9].*$|^[a-z0-9].*\W.*[A-Z].*$|^[a-z0-9].*[A-Z].*\W.*$|^\W.*[a-z0-9].*[A-Z].*$|^\W.*[A-Z].*[a-z0-9].*$/

and I'm not even sure it will work well enough

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
Thanks for the reply. This is pretty much the way I thought I would have to do it, different variations of "or" statements to match all possible patterns... Thanks for the information. This works well, except it treats lower case letters and numbers the same... Anyway, thanks for all the help.
 
but this has to be done in a ONE line regular expresion
Why? Surely, to meet your requirements, it just has to be done?
Code:
if ($var =~ /\W/ && $var =~ /[A-Z]/ && $var =~ /[a-z]/) {
   ..
}

Steve

[small]"Every program can be reduced by one instruction, and every program has at least one bug. Therefore, any program can be reduced to one instruction which doesn't work." (Object::perlDesignPatterns)[/small]
 
Another option would be to use positive-look-aheads.
Code:
my @strings = ('Aa!', 'A!', 'a!', 'aA', 'Testuser1$%');

foreach (@strings) {
    if (m/^(?=.*[A-Z])(?=.*[a-z])(?=.*\W)/) {
        print "$_\n";
    }
}
 
Thanks rharsh. That seems to be a "cleaner" looking way of going about it. Now, the hard part....trying to figure why it's working :p Thanks again.
 
Hey rharsh, can you explain to me how that works if .* is supposed to be greedy. If it's greedy, wouldn't .* eat the whole string and fail the match? This is also confusing me w/ the first response to my question.
 
Ah, that makes sense.. Is this also true with (?: ...??
 
Well, I can only apologise for my crude efforts. Star for rharsh, I think...

Steve

[small]"Every program can be reduced by one instruction, and every program has at least one bug. Therefore, any program can be reduced to one instruction which doesn't work." (Object::perlDesignPatterns)[/small]
 
The lookaround assertions are quite handy, especially for shortening those long patterns. I don't use them much because they still confuse me. Like this pattern:

m/^(?=.*[A-Z])(?=.*[a-z])(?=.*\W)/

does it have to start from the beginning of the string for each new assertion? Do they return a match/no match back to the regexp engine as soon as possible for each assertion or as late as possible? The lack of an ending string anchor bothers me too but apparently it's not necessary and maybe should be avoided?

------------------------------------------
- Kevin, perl coder unexceptional! [wiggle]
 
^5 KevinADC i'm still confused w/ this as well.
 
Kevin,

In this case, Yes.
This example would be early, given that all that is being returned is a true/false.


Ericse,

Non-capturing groups (?:) are not zero-width, and consume characters from the string.


And yes, they confuse me too, esp. those with lookbehinds.

I think I learn something about regex's most times I see a post from Kevin or ishnid (... and now rharsh)
 
brigmar, if this is the case... that (?: are non-zero-width, then how does:
Code:
/^[A-Z].*[a-z0-9].*\W.*$|^[A-Z].*\W.*[a-z0-9].*$|^[a-z0-9].*\W.*[A-Z].*$|^[a-z0-9].*[A-Z].*\W.*$|^\W.*[a-z0-9].*[A-Z].*$|^\W.*[A-Z].*[a-z0-9].*$/

work?

If .* is greedy, wouldn't it up the entire string and fail? That's what I would assume, but it doesn't work like that. This regexp works (albeit not as good as the rharsh posted). Mind explaining?
 
Ack, my last question didn't have (?: but regardless, how does that work if .* is supposedly greedy? Thanks
 
A regex with a 'greedy' .* doesn't mean that the .* eats up the string. It means that given the choice of two (or more) choices of possible matches, a greedy .* will eat up the most characters THAT STILL ALLOW THE MATCH. A non-greedy .* will eat up the least amount of characters THAT STILL ALLOW THE MATCH.

In your example, the 'greediness' has no effect.
 
Ah, that makes sense. Thanks for the help :)
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top