JQuery + Regex: Grouping and Counting - regex

I have been reading and playing with regex used in JQuery, and have got things partially working but don't seem to be tracking on the failing regex.
The specific problem – I think – has to do with 'look[ing]behind'.
Thanks to CodeJockey for the original direction. Here's my updated code:
<script type="text/javascript">
jQuery(document).ready(function($) {
$.validator.addMethod("lccharReqs", function(value, element) {
var lc = /(?=.*[a-z])/;
return this.optional(element) || lc.test(value);
}, "Your password should contain at least one lowercase letter!");
$.validator.addMethod("uccharReqs", function(value, element) {
var uc = /(?=.*[A-Z])/;
return this.optional(element) || uc.test(value);
}, "Your password should contain at least one uppercase letter!");
$.validator.addMethod("nccharReqs", function(value, element) {
var nc = /(?=.*[0-9])/;
return this.optional(element) || nc.test(value);
}, "Your password should contain at least one number!");
$.validator.addMethod("speccharReqs", function(value, element) {
var sc = /(?<=.*[\!\#\#\$\%\&\?\-\_])/;
return this.optional(element) || sc.test(value);
}, "Your password should contain at least one special character!");
$("#new_noisuf_pwd").validate({
rules: {
inf_field_Password: {
required: true,
minlength: 8,
lccharReqs: true,
uccharReqs: true,
nccharReqs: true,
speccharReqs: true
},
pwd_confirm : {
equalTo: "#inf_field_Password"
}
},
messages: {
inf_field_Password: {
required: "Please enter a password!",
minlength: "Your password must be at least 8 characters!",
maxlength: "Your password cannot be more the 12 characters!"
},
pwd_confirm : {
equalTo: "Your passwords does not match!"
}
}});
});
</script>
The reason I'm leaning towards the 'lookbehind' is:
Enter aaaaaaaa - I get the uppercase error...
Enter Aaaaaaaa - I get the number error...
Enter 1Aaaaaaa - I get the special character error, but
Enter Passw0rd - I get no error.
Really trying to learn this and have been reading a lot, but I'm stuck.
Thanks!
[original question]
I am using the 'validation' plugin and am adding a method as follows:
jQuery.validator.addMethod("charReqs", function(value, element) {
return this.optional(element) || /^(([a-z]{1})([A-Z]{1})([0-9]{1})([\!\#\#\+\-]{1})) *$/.test(value);
}, "One lowercase letter, one capital letter, one number and one of the characters listed above - please!");
1.) Do I have the syntax correct to check for 1 l-c char, 1 u-c char, 1 num and 1 of a list of special chars somewhere in the string:
/^ ( ([a-z]{1}) ([A-Z]{1}) ([0-9]{1}) ([\!\#\#\+\-]{1}) ) *$/
2.) Am I grouping this correctly?
3.) If not, please explain.
Thanks

POINT BY POINT ANSWER
1) Not really, no
Your expression specifies a string that begins with exactly one lower case character [a-z], followed by exactly one upper case character[A-Z], followed by exactly one digit [0-9], followed by exactly one of the following characters: !, #, #, +, -, followed by zero or more spaces, then the end of the string :-/
2) Nope - not grouped correctly
3) More complex explanation: the character classes ([a-z], [0-9], etc) are correct enough (though the {1} part and escaping \ characters are redundant. However, you need to have them in what's called a "lookahead" that matches matching anything followed by those characters.
Instead of saying "match one of these"
([a-z])
You would say essentially "lookahead and see if you can match any text followed by one of these, then come back"
(?=.*[a-z])
To match two characters somewhere in the string, you would do like this:
(?=(.*[a-z]){2})
As for the whole expression, to match one of each of the characters you were looking for, use this:
^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[\!\#\#\+\-])$
To require two or more of each, you would use the {#} notation, like
^(?=(.*[a-z]){2})(?=(.*[A-Z]){2})(?=(.*[0-9]){2})(?=(.*[\!\#\#\+\-]){2})$
You could also enforce a minimum length (like 10 characters) like
^(?=(.*[a-z]){2})(?=(.*[A-Z]){2})(?=(.*[0-9]){2})(?=(.*[\!\#\#\+\-]){2}).{10,}$
HOWEVER
I would recommend separating these out into separate expressions (I'm guessing something like jQuery.validator.addMethod("...", function(...){...}, "Reason...").addMethod(...).addMethod(...).etc() that each tell the user what's missing. So you'd have one looking for lowercase characters, saying "you need a lower case character", then one looking for digits saying "you need a digit", etc...
Also, the special characters there are really restrictive, so I hope you allow some other ones as well (as long as those are provided (?))
and finally... see http://xkcd.com/936/

Related

Botkit for Slack using regex patterns in conversations

I'm running into an issue using regex patterns in botkit conversations that I can't quite work through, and though I'm sure someone else will have a quick answer, I'm utterly stumped.
I'm building a conversation that will store user information in a JSON file, but I need a small amount of validation on the entries before I store them. Specifically, the inputs must either be a full name (any number of words greater than one with a space between them) or a domain username in the format of domain\name with no spaces and the correct domain.
Using RegExr, I came up with the following regEx expressions which match in that user interface but which will not match when placed in the "pattern" attribute of the botkit conversation node:
\w+( +\w+)+ for the any number of words with a space between them.
domain+(\\+\w+) for the specified domain + a username
But when I use these in the botkit conversation, they're not matching -- so I'm not quite clear on what I'm doing wrong.
Here's the code snippet in which these are being used:
bot.startConversation(message, function (err, convo) {
convo.say("I don't know who you are in TFS. Can you tell me?");
convo.addQuestion("You can say \"no\" or tell me your TFS name or your domain name (eg: \"domain\\username)", [
{
pattern: bot.utterances.no,
callback: function (response, convo) {
convo.say("Okay, maybe another time then.");
convo.next();
}
},
{
pattern: '\w+( +\w+)+',
callback: function (response, convo) {
convo.say("You said your TFS name is " + response.text);
convo.next();
}
},
{
pattern: 'domain+(\\+\w+)+',
callback: function (response, convo) {
convo.say("You said your TFS name is " + response.text);
convo.next();
}
},
{
default: true,
callback: function (response, convo) {
convo.say("I didn't understand that.");
convo.repeat();
convo.next();
}
}
], {}, 'default');
You need to use double backslashes, and fix the backslash before the closing single quote in the first regex string literal:
pattern: '\\w+( +\\w+)+',
pattern: 'domain(\\\\\\w+)+',
The first pattern:
\\w+ - 1+ word chars
( +\\w+)+ - 1 or more sequences of 1 or more spaces and then 1 or more word chars
Domain regex:
domain - a domain
(\\\\\\w+)+ - 1 or more occurrences of
\\\\ - 1 backslash
\\w+ - 1 or more word chars.

Regex for validate password in ReactJS

Can we do regex pattern checking for password validation in reactJS?
Since I am new to reactJS, I need regex pattern for validating the password.
Following are the conditions for validating password.
a) Password should contains one Capital letter
b) It should start with special character # or #
c) It should not contain any vowel a,e,i,o,u letters
d) It should be alphanumeric.
e) Length of password should be between range 8 to 14
The simpliest way is to check all rules separately.
There's a function i wrote for you:
function password_validate(password) {
var re = {
'capital' : /[A-Z]/,
'digit' : /[0-9]/,
'except' : /[aeiou]/,
'full' : /^[##][A-Za-z0-9]{7,13}$/
};
return re.capital .test(password) &&
re.digit .test(password) &&
!re.except .test(password) &&
re.full .test(password);
}
Or the same function in one line:
function password_validate(p) {
return /[A-Z]/.test(p) && /[0-9]/.test(p) && !/[aeiou]/.test(p) && /^[##][A-Za-z0-9]{7,13}$/.test(p);
}
This regex will work :
^[##](?=.{7,13}$)(?=\w{7,13})(?=[^aeiou_]{7,13})(?=.*[A-Z])(?=.*\d)
Explanation
^[##] Starts with # or #
Now we can add some conditions this way :
(?=condition)(?=condition)(?=condition)
This means "match condition but after that continue matching at the original match-point."
You can add as many conditions as you want, and this will be an "and."
(?=.{7,13}$) Length of password should be between range 8 to 14
(?=\w{7,13}) It should be alphanumeric.
(?=[^aeiou_]{7,13}) It should not contain any vowel a,e,i,o,u letters or underscore which is matched by \w
(?=.*[A-Z]) Password should contains a Capital letter
(?=.*\d) It should be alphanumeric so it should contain a digit
Demo
If you want to check all rules in one pass - try this formula:
^([##](?=[^aeiou]{7,13}$)(?=[[:alnum:]]{7,13}$)(?=.*[A-Z]{1,}.*$).+)$
Demo
Standard one - /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!##\$%\^&\*])(?=.{8,})/.test(paswrd)

Issues with Regular Expressions

I understand the concept of repetition 0 or more times (*) and grouping '()' on there own, but I'm having trouble understanding them given practice examples.
For example, (yes)* contains both the empty set and the word 'yes', but not y or ss. I assume that it doesn't contain those words because of grouping, but would that mean the word 'yesyes' is also valid as the group has been repeated?
In contrast, I assume with the Regular Expression 'yes*', any character can be repeated. For example 'y', 'ye' 'es' 'yes', 'yy'. However the solutions we have been provided with state that the word 'y' isn't contained. I'm confused.
Your understanding of (yes)* is correct ...
(yes)* matches the string "yes" (exactly - no shorter, no longer) 0 or more times - ie the empty string or yes,yesyes, yesyesyesyesyesyes etc
But your understanding of yes* is NOT correct ...
yes* matches the string "ye" followed by 0 or more "s" characters - ie ye,yes,yess,yessssssss
The "zero or more" * modifier applies only to the character or group immediately preceding it.
In the first example, we have the group (yes)* - this will match '', 'yes', 'yesyes', etc.
In the second example, yes*, the modifier applies only to the letter s. It will match 'ye', 'yes', 'yess', etc.
If this is not clear then perhaps you can elaborate a little on the source of your confusion.

Regex expression for password rules

I have a requirement for password rules. Following are the rules.
The password must follow the following guidelines:
Be at least eight characters long
Contain 3 of these 4 options: lower case letter, upper case letter, number, or special character
When user specifies a password that does not meet the above rules, return message stating:
Password must be at least 8 characters long and contain 3 of the 4 following options:
Lower case letter (a-z)
Upper case letter (A-Z)
Number (0-9)
Special character (!##$%^&')
Please help me to get a regex expression to handle above conditions.
i appreciate all your help. following is the solution for my requirement
if(password.matches("^(?=.*[0-9]).{1,}$")){
validCount++;
}
if(password.matches("^(?=.*[a-z]).{1,}$")){
validCount++;
}
if(password.matches("^(?=.*[A-Z]).{1,}$")){
validCount++;
}
if(password.matches("^(?=.*[##$%^&+=]).{1,}$")){
validCount++;
}
return validCount >= 3 ? true : false;
Thanks,
Ramki
This is, if you want an elegant regex, as close as you can get
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!##$%^&'])[^ ]{8,}$
The basic idea is to use a technique called "positive lookahead" :
(?=.*PutHereWhatYouWantToAllow)
Your extra requirement 3 out of 4 is not easy to solve with regexes cause you cannot make them count basically.
You could write out the necessary permutations of the above regex (tell me if it doesn't make sense) but that would make a very long regex.
What you could do is write out the permutations in code so that the regex stays maintainable since you are not repeating the patterns literally.
I'll have a shot if I you tell me your language (C#?) cause it's a good challenge.
Update 1
Here is the regex that will match at least 3 of your requirements (4 is also allowed), just for the challenge of it. Don't use this in production but loop in the language with individual regexes as mentioned in the comments.
^((?=.[a-z].[A-Z].[\d])|(?=.[a-z].[\d].[A-Z])|(?=.[A-Z].[a-z].[\d])|(?=.[A-Z].[\d].[a-z])|(?=.[\d].[a-z].[A-Z])|(?=.[\d].[A-Z].[a-z])|(?=.[a-z].[A-Z].[!##$%^&'])|(?=.[a-z].[!##$%^&'].[A-Z])|(?=.[A-Z].[a-z].[!##$%^&'])|(?=.[A-Z].[!##$%^&'].[a-z])|(?=.[!##$%^&'].[a-z].[A-Z])|(?=.[!##$%^&'].[A-Z].[a-z])|(?=.[a-z].[\d].[!##$%^&'])|(?=.[a-z].[!##$%^&'].[\d])|(?=.[\d].[a-z].[!##$%^&'])|(?=.[\d].[!##$%^&'].[a-z])|(?=.[!##$%^&'].[a-z].[\d])|(?=.[!##$%^&'].[\d].[a-z])|(?=.[A-Z].[\d].[!##$%^&'])|(?=.[A-Z].[!##$%^&'].[\d])|(?=.[\d].[A-Z].[!##$%^&'])|(?=.[\d].[!##$%^&'].[A-Z])|(?=.[!##$%^&'].[A-Z].[\d])|(?=.[!##$%^&'].[\d].[A-Z]))[^ ]{8,}$
Update 2
This is the approach to take in java
From the comments I read that you are testing like the following
lowercase "^[a-z]*$";
uppercase "^[A-Z]*$";
digits="^[0-9]*$";
I don't think you are on the right track here. The lowercase will only report success if all characters are lowercase, and not just one. Same remark for the rest.
These are the 4 individual regexes of which at least 3 should report a match
[a-z]
[A-Z]
\d
[!##$%^&']
Here is the test that the password should not contain a space
^[^ ]*$
The test for at least 8 characters
.{8,}
So I split the requirements and not combine them. This should make for more readable code especially if one starts with regexes.
Here's how I would do it:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ValidatePassword
{
public static void main (String[] args)
{
String pw = "abaslkA3FLKJ";
// create an array with 4 regex patterns
Pattern [] patternArray = {
Pattern.compile("[a-z]"),
Pattern.compile("[A-Z]"),
Pattern.compile("[0-9]"),
Pattern.compile("[&%$#]")
};
int matchCount = 0;
// iterate over the patterns looking for matches
for (Pattern thisPattern : patternArray) {
Matcher theMatcher = thisPattern.matcher(pw);
if (theMatcher.find()) {
matchCount ++;
}
}
if (matchCount >= 3) {
System.out.println("Success");
}
else {
System.out.println("Failure: only " + matchCount + " matches");
}
}
}
I only added a few special characters to the 4th pattern... You'll have to modify it for your needs. You may need to escape certain characters with a backslash. You may also want to add other constraints like checking for no spaces. I'll leave that up to you.

How does Sencha Touch matcher work?

I am trying to create a simple matcher that matches any string consisting of alphanumeric characters. I tried the following:
Ext.regModel('RegistrationData', {
fields: [
{name: 'nickname',type: 'string'},
],
validations: [
{type: 'format', name: 'nickname', matcher: /[a-zA-Z0-9]*/}
]
});
However this does not work as expected. I did not find any documentation on how should a regular expression in a matcher look like.
Thank you for help.
I found a blog on sencha.com, where they explain the validation.
I have no idea what sencha-touch is, but maybe it helps, when you tell us what you are giving to your regex, what you expect it to do, and what it actually does (does not work as expected is a bit vague). According to the blog it accepts "regular expression format", so for your simple check, it should be pretty standard.
EDIT:
As a wild guess, maybe you want to use anchors to ensure that the name has really only letters and numbers:
/^[a-zA-Z0-9]*$/
^ is matching the start of the string
$ is matching the end of the string
Your current regex /[a-zA-Z0-9]*/ would match a string containing zero or more occurrences of lower or upper case characters (A-Z) or numbers anywhere in the string. That's why Joe#2, J/o/e, *89Joe as well as Joe, Joe24andjOe28` match - they all contain zero or more subsequent occurrences of the respective characters.
If you want your string to contain only the respective characters you have to change the regex according to stema's answer:
/^[a-zA-Z0-9]*$/
But this has still one problem. Due to the * which meas zero or more occurrences it also matches an empty string, so the correct string should be:
/^[a-zA-Z0-9]+$/
with + meaning one or more occurrences. This will allow nicknames containing only one lowercase or uppercase character or number, such as a, F or 6.