paschim Posted August 15, 2008 Share Posted August 15, 2008 Guys, please try and help me with this, I need a regex, that does the following:- Check if a string is with 4-15 characters Check if there is space or any character other than the accepted ones! Illegal characters: ~`@#$%^&*()-+=|\'":;?/>.,< Accepted characters: Numbers, alphabets, ! , _ Also i would like it to make sure the string begins with a letter or number And no ! or_ can stay side by side, meaning no !! or __ i know this is a lot to ask, but please try to help! Quote Link to comment Share on other sites More sharing options...
nrg_alpha Posted August 15, 2008 Share Posted August 15, 2008 I *think* I got it.. slightly ugly, but my tests seem to hold up... $str = array('t!_es!_ti!123' , 't!e!!_sg_!123', 'testing123ABCFDS', 't!__e_s_t123', 'this space' , 'this-test', '-testing123'); foreach($str as $val){ if(strlen($val) > 3 && strlen($val) < 16){ if(preg_match('#^[a-z0-9]+((!_)|(_!)|!|_)?([a-z0-9]+((!_)|(_!)|!|_)?)*$#i', $val)){ echo $val . ' = legal.' . '<br />'; } else { echo $val . ' = illegal.' . '<br />'; } } else { echo $val . ' = illegal: (not between 4 and 15 characters).' . '<br />'; } } ouputs: t!_es!_ti!123 = legal. t!e!!_sg_!123 = illegal. testing123ABCFDS = illegal: (not between 4 and 15 characters). t!__e_s_t123 = illegal. this space = illegal. this-test = illegal. -testing123 = illegal. Is that what you are looking for? It may not be the most elegant solution..but if I understand it all correctly.. Cheers, NRG Quote Link to comment Share on other sites More sharing options...
paschim Posted August 15, 2008 Author Share Posted August 15, 2008 Cool...thanks man! Though i cant understand it....it gets the job done...so thanks a lot! Quote Link to comment Share on other sites More sharing options...
nrg_alpha Posted August 15, 2008 Share Posted August 15, 2008 ok.. I'll explain..the hard part (as I'm sure you can understand the rest ) instead of using '/' delimiters, I prefer to use the '#' characters.. so without further ado.. focusing strictly on this part: preg_match('#^[a-z0-9]+((!_)|(_!)|!|_)?([a-z0-9]+((!_)|(_!)|!|_)?)*$#i', $val) So let's have a look inside the expression (after the first '#' delimiter). I'll name these in chunks of sequences for easier reference sake. Sequence-01: ^[a-z0-9]+ <--- this means the string must start with any letter of the alphabet or any number (one or more times (because of the '+' character). Sequence-02: ((!_)|(_!)|!|_)? <--- This looks messy.. but isn't all that bad.. what this does is next looks for either both '!' and / or '_' characters.. but what I have done here is simply check to see if the sequence is either: !_ -or- _! -or- ! -or _ . I do this because I know by the rules you set, the expression should allow to have one of each next to eachother (but not two of the same together). The '?' at the end basically means no more than one time.. so at this point, the string must start with a letter or number (one or more times, and then contain any of the ! or _ as just descibed (but as optional). Sequence-03: ([a-z0-9]+((!_)|(_!)|!|_)?)* <---- This part was the trickiest.. notice all the sets of brackets..to avoid confusion, I made them into groups (the brackets). At this point, just understand that the very first '(' and very last bracket ')' in this line is checked (matched) zero or more times (due to the '*' character). I'll strip this down and explain this in two parts (ignoring the the first and last bracket as well as the asterisk).. Sequence-03a: [a-z0-9]+ <--- ok.. so here, the next sequence matched against checks for any letter or number (one or more times.. because of the '+' character after the character class.. then.. when the match runs out of letters or numbers, the next sequence must follow for this entire string match to be true.. and that is Sequence-03b: ((!_)|(_!)|!|_)? <--- so while this is a mess of groups (brackets), this is essecially the same explaination as Sequence-02. But since Sequence-03 is completely surrounded by: ( .... )*, this tells the expression to keep checking (matching) this pattern zero or more times (because of the '*' Asterisk). so because this is zero or more times.. it is completely optional.. thus meaning that even if a string doesn't end with a ! or _ or any acceptable combination of those, it still works. And finally, the expression is capped off by the closing delimiter and pattern modifier: $#i <--- The dollarsign means end of string to match against.. and since we are interesed in upper or lower case letters, we add the 'i' modifier.. this way, the expression doesn't care if the letters being matched is upper or lowercase.. without this 'i', the expression would only match lowercase letters (as I only show the range of lowercase characters in the expression). I'm not sure if I explained this right. if not.. don't be shy.. I'll try and help out with any part you are not sure on. Now, I'm sure some more experienced coders can come up with something even more streamlined.. but in my limited knowledge, this is what I came up with. All in all, it works, and this is what is important.. but I'm sure there can be improvements. Cheers, NRG Quote Link to comment Share on other sites More sharing options...
paschim Posted August 15, 2008 Author Share Posted August 15, 2008 ok thanks for the explanation!! just one question: how do you enforce the 4-15 limit.....and what can i do to change it if needed? Quote Link to comment Share on other sites More sharing options...
nrg_alpha Posted August 15, 2008 Share Posted August 15, 2008 ok thanks for the explanation!! just one question: how do you enforce the 4-15 limit.....and what can i do to change it if needed? The limits are found in this line (which is not part of the expression): if(strlen($val) > 3 && strlen($val) < 16){ So you can adjust the '3' or '16' numbers to something else.. so if you need something between 10 and 20, that line would be changed to: if(strlen($val) > 9 && strlen($val) < 21){ Quote Link to comment Share on other sites More sharing options...
paschim Posted August 15, 2008 Author Share Posted August 15, 2008 oh ok....thanks! Quote Link to comment Share on other sites More sharing options...
effigy Posted August 18, 2008 Share Posted August 18, 2008 Here's my go: <pre> <?php $tests = array( 't!_es!_ti!123', 't!e!!_sg_!123', 'testing123ABCFDS', 't!__e_s_t123', 'this space', 'this-test', '-testing123' ); foreach ($tests as $test) { echo "$test — "; echo preg_match('/ \A [a-z\d] (?[\w!])(?(?<=[!_])(?!\1))){3,14} \z /ix', $test) ? 'Valid' : 'Invalid' ; echo '<br>'; } ?> </pre> Quote Link to comment Share on other sites More sharing options...
nrg_alpha Posted August 18, 2008 Share Posted August 18, 2008 Effigy, when I pasted and tested your code, all was well except for one: the array entry 'testing123ABCFDS' results as invalid, yet it contains only legal characters per the OP's request: testing123ABCFDS — Invalid EDIT: never mind.. it was its length that voids it. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.