Here is something I've never tried to do before with regex - match multiple "rules" but within one regex. Consider for example password validation. Normally this requires a string pass multiple rules:
- Must be N characters long
- Must contain lower case characters
- Must container upper case characters
I can do any of those rules easily enough but in the past I've done it "long" hand:
<cfloop index="test" array="#s#">
<cfoutput>#test# ok? </cfoutput> <cfif len(test) gte 7 and reFind("[a-z]", test) and reFind("[A-Z]", test)>
yes
<cfelse>
no
</cfif><br/> </cfloop>
<cfset s = ["aaaa","aAa","AAAA","a9", "A9", "aA9","aaaAAA7"]>
That works - but it seemed like there must be some way with regex to say "I want to ensure A matches, and B, and C, but I don't care where." My Google-fu failed until I came across this excellent blog post: Password Validation via Regular Expression. In this blog entry, Nilang Shah, makes use of a "positive lookahead." These are items you can ensure match in a regex but don't get returned in the match.
Let me be honest - I don't quite get how this stuff works. His example though worked perfectly. I took his third example and removed the requirement for a special character and got this:
<cfloop index="test" array="#s#">
<cfoutput>#test# ok? </cfoutput>
<cfset regex = "^.(?=.{7,})(?=.\d)(?=.[a-z])(?=.[A-Z]).*$"> <cfif reFind(regex, test)>
yes
<cfelse>
no
</cfif><br/> </cfloop>
<cfset s = ["aaaa","aAa","AAAA","a9", "A9", "aA9","aaaAAA7"]>
I don't quite get why we have to anchor it nor do I get the .* in the look aheads. But I can say it works great.