I need help on regular expression on the condition (4) below:
Begin with a-z
End with a-z0-9
allow 3 special characters like ._-
The characters in (3) must be followed by alphanumeric characters, and it cannot be followed by any characters in (3) themselves.
Not sure how to do this. Any help is appreciated, with the sample and some explanations.
You can try this:
^(?=.{5,10}$)(?!.*[._-]{2})[a-z][a-z0-9._-]*[a-z0-9]$
This uses lookaheads to enforce that username must have between 5 and 10 characters (?=.{5,10}$), and that none of the 3 special characters appear twice in a row (?!.*[._-]{2}), but overall they can appear any number of times (Konrad interprets it differently, in that the 3 special characters can appear up to 3 times).
Here's a test harness in Java:
String[] test = {
"abc",
"abcde",
"acd_e",
"_abcd",
"abcd_",
"a__bc",
"a_.bc",
"a_b.c-d",
"a_b_c_d_e",
"this-is-too-long",
};
for (String s : test) {
System.out.format("%s %B %n", s,
s.matches("^(?=.{5,10}$)(?!.*[._-]{2})[a-z][a-z0-9._-]*[a-z0-9]$")
);
}
This prints:
abc FALSE
abcde TRUE
acd_e TRUE
_abcd FALSE
abcd_ FALSE
a__bc FALSE
a_.bc FALSE
a_b.c-d TRUE
a_b_c_d_e TRUE
this-is-too-long FALSE
See also
regular-expressions.info/Lookarounds, limiting repetitions, and anchors
So basically:
Start with [a-z].
Allow a first serving of [a-z0-9], several times. 1)
Allow
at most one of [._-], followed by
at least one of [a-z0-9]
three times or less.
End with [a-z0-9] (implied in the above).
Which yields:
^[a-z][a-z0-9]*([._-][a-z0-9]+){0,3}$
But beware that this may result in user names with only one character.
1) (posted by #codeka)
try that:
^[a-zA-Z](([\._\-][a-zA-Z0-9])|[a-zA-Z0-9])*[a-z0-9]$
1) ^[a-zA-Z]: beginning
2) (([._-][a-zA-Z0-9])|[a-zA-Z0-9])*: any number of either alphanum, or special char followed by alphanum
3) [a-z0-9]$
Well, because I feel like being ... me. One Regex does not need to rule them all -- and for one of the Nine, see nqueens. (However, in this case there are some nice answers already; I'm just pointing out a slightly different approach.)
function valid(n) {
return (n.length > 3
&& n.match(/^[a-z]/i)
&& n.match(/[a-z0-9]$/i)
&& !n.match(/[._-]{2}/)
}
Now imagine that you only allow one ., _ or - total (perhaps I misread the initial requirements shrug); that's easy to add (and visualize):
&& n.replace(/[^._-]/g, "").length <= 1
And before anyone says "that's less efficient", go profile it in the intended usage. Also note, I didn't give up using regular expressions entirely, they are a wonderful thing.
Related
I am trying to create a regular expression for a password field that checks to see if the input contains a mix of at least two characters sets (alphabetic, numeric, punctuation, special character). In addition, the first and last character cannot be numeric and the length must be at least 8 characters long.
I have never dealt with conditional logic for regular expressions, so it's probably why I'm having such a hard time. So far, this (but it's not working as intended):
(?=.{8,})(\d.*[a-zA-Z])|(?=.{8,})([a-zA-Z].*\d)|(?=.{8,})(\W.*\d)|(?=.{8,})(\d.*\W)|(?=.{8,})(\W.*[a-zA-Z])|(?=.{8,})([a-zA-Z].*\W)|(?=.{8,})([a-z].*[A-Z])|(?=.{8,})([A-Z].*[a-z])
Personally, I wouldn't do this with a single regex. Why not run it through a set of simpler ones, just to save yourself the inevitable maintenance headaches down the line? Something like (in order, in pseudocode):
// First and last are non-numeric and length check
if (!regex_check(pass, /^[^0-9].{6}.*[^0-9]$/)) return false
regexes = {/[a-zA-Z]/, /[0-9]/, /\p{P}|\p{Sc}|\^/} // Different character categories
numCategories = 0
for r in regex
if (regex_check(pass, r)) numCategories += 1
if numCategories >= 2 return true
return false
I'm a Regex newbie, and so far have only used it for simple things, like "must be a number or letter". Now I have to do something a bit more complex.
I need to use it to validate a password, which must be 8-16 characters, free of control/non-printing/non-ASCII characters, and must have at least three of the following:
one capital letter
one lowercase letter
one number 0-9
one symbol character ($, %, &, etc.)
I'm thinking what I have to do is write something like "one capital letter, lowercase letter and number, OR one capital letter, lowercase letter and one symbol, OR one capital letter, one number or one symbol, OR...." to cover all possible "3 out of 4" combinations, but that seems excessive. Is there a simpler solution?
The correct way to do this is to check all of the five conditions separately. However, I assume there is a reason you want a regex, here you go:
/^((?=.*[A-Z])(?=.*[a-z])(?=.*\d)|(?=.*[a-z])(?=.*\d)(?=.*[\$\%\&])|(?=.*[A-Z])(?=.*\d)(?=.*[\$\%\&])|(?=.*[A-Z])(?=.*[a-z])(?=.*[\$\%\&])).{8,16}$/
Explanation:
We want to match the whole thing, hence we surround it with ^$
.{n,m} matches between n and m characters (8 and 16 in our case).
The general way you can check if a string contains something, without actually matching it is by using positive lookahead (?=.*X), where X is the thing you want to check. For example, if you want to make sure the string contains a lowercase letter you can do (?=.*[a-z]).
If you want to check if a string contains X, Y and Z, but without actually matching them, you can use the previous recipe by appending the three lookaheads (?=.*X)(?=.*Y)(?=.*Z)
We use the above to match three of the four things mentioned. We go through all possible combinations with |(or) - cCD|cDS|CDS|CcS (c = lowercase letter, C = capital letter, D = digit, S = special)
See it in action
The best way to do this is by checking each condition separately. Performance will suffer if you try to fit all conditional criteria into one expression (see the accepted answer). I also highly recommend against limiting the length of the password to 16 chars — this is extremely insecure for modern standards. Try something more like 64 chars, or even better, 128 — assuming your hashing architecture can handle the load.
You also didn't specify a language, but this is one way to do it in JavaScript:
var pws = [
"%5abCdefg",
"&5ab",
"%5abCdef",
"5Bcdwefg",
"BCADLKJSDSDFlk"
];
function pwCheck(pw) {
var criteria = 0;
if (pw.toUpperCase() != pw) {
// has lower case letters
criteria++;
}
if (pw.toLowerCase() != pw) {
// has upper case letters
criteria++;
}
if (/^[a-zA-Z0-9]*$/.test(pw) === false) {
// has special characters
criteria++;
}
if (/\d/.test(pw) === true) {
// has numbers
criteria++;
}
// returns true if 3 or more criteria was met and length is appropriate
return (criteria >= 3 && pw.length >= 8 && pw.length <= 16);
}
pws.forEach(function(pw) {
console.log(pw + ": " + pwCheck(pw).toString());
});
Not sure if its a iOS thing, the regex with "d" for digits [0-9] wasn't working as expected, example String that had issues = "AAAAAA1$"
The fix below works fine in Objective-C and Swift 3
^((?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])|(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[^a-zA-Z0-9])|(?=.*?[A-Z])(?=.*?[0-9])(?=.*?[^a-zA-Z0-9])|(?=.*?[a-z])(?=.*?[0-9])(?=.*?[^a-zA-Z0-9])).{8,16}$
How do I specify that there are several options for a string in a search?
For example, I want to find any combination that start with either jspPar, btn or jspAtt that ends with the letter K.
Also - I need to replace it with a string depending on the original prefix.
for example, if the prefix was jspPar I need to replace it with the letter P. (and, let's say, B and A for btn and jspAtt accordingaly).
Is
\(jsPar\|btn\|jspAtt\)[^ \t]*K
what you are looking for?
The \(jsPar\|btn\|jspAtt\) says “at this point, match any of these alternatives”, then [^ \t]* says “at this point, match any amount (incl. zero) of space or tab characters”, and K of course means “at this point match a K”.
For your added question could do something like this:
%s/\(jsPar\|btn\|jspAtt\)[^ \t]*\zsK/\=submatch(1) == 'jsPar' ? 'P' : submatch(1) == 'btn' ? 'B' : 'A' /g
(The \zs says “consider the match to have started at this point” so only the “K” will be replaced.)
But I would only do that if I had to do the substitution in a single pass. Otherwise I’d just run three s///s:
%s/jspAtt[^ \t]*\zsK/A/g
%s/jsPar[^ \t]*\zsK/P/g
%s/btn[^ \t]*\zsK/B/g
Given command history, that’s much less typing, and is also very unlikely to require debugging, whereas that’s always a potentiality when specifying any computation.
Is it possible to write a regular expression that matches all strings that does not only contain numbers? If we have these strings:
abc
a4c
4bc
ab4
123
It should match the four first, but not the last one. I have tried fiddling around in RegexBuddy with lookaheads and stuff, but I can't seem to figure it out.
(?!^\d+$)^.+$
This says lookahead for lines that do not contain all digits and match the entire line.
Unless I am missing something, I think the most concise regex is...
/\D/
...or in other words, is there a not-digit in the string?
jjnguy had it correct (if slightly redundant) in an earlier revision.
.*?[^0-9].*
#Chad, your regex,
\b.*[a-zA-Z]+.*\b
should probably allow for non letters (eg, punctuation) even though Svish's examples didn't include one. Svish's primary requirement was: not all be digits.
\b.*[^0-9]+.*\b
Then, you don't need the + in there since all you need is to guarantee 1 non-digit is in there (more might be in there as covered by the .* on the ends).
\b.*[^0-9].*\b
Next, you can do away with the \b on either end since these are unnecessary constraints (invoking reference to alphanum and _).
.*[^0-9].*
Finally, note that this last regex shows that the problem can be solved with just the basics, those basics which have existed for decades (eg, no need for the look-ahead feature). In English, the question was logically equivalent to simply asking that 1 counter-example character be found within a string.
We can test this regex in a browser by copying the following into the location bar, replacing the string "6576576i7567" with whatever you want to test.
javascript:alert(new String("6576576i7567").match(".*[^0-9].*"));
/^\d*[a-z][a-z\d]*$/
Or, case insensitive version:
/^\d*[a-z][a-z\d]*$/i
May be a digit at the beginning, then at least one letter, then letters or digits
Try this:
/^.*\D+.*$/
It returns true if there is any simbol, that is not a number. Works fine with all languages.
Since you said "match", not just validate, the following regex will match correctly
\b.*[a-zA-Z]+.*\b
Passing Tests:
abc
a4c
4bc
ab4
1b1
11b
b11
Failing Tests:
123
if you are trying to match worlds that have at least one letter but they are formed by numbers and letters (or just letters), this is what I have used:
(\d*[a-zA-Z]+\d*)+
If we want to restrict valid characters so that string can be made from a limited set of characters, try this:
(?!^\d+$)^[a-zA-Z0-9_-]{3,}$
or
(?!^\d+$)^[\w-]{3,}$
/\w+/:
Matches any letter, number or underscore. any word character
.*[^0-9]{1,}.*
Works fine for us.
We want to use the used answer, but it's not working within YANG model.
And the one I provided here is easy to understand and it's clear:
start and end could be any chars, but, but there must be at least one NON NUMERICAL characters, which is greatest.
I am using /^[0-9]*$/gm in my JavaScript code to see if string is only numbers. If yes then it should fail otherwise it will return the string.
Below is working code snippet with test cases:
function isValidURL(string) {
var res = string.match(/^[0-9]*$/gm);
if (res == null)
return string;
else
return "fail";
};
var testCase1 = "abc";
console.log(isValidURL(testCase1)); // abc
var testCase2 = "a4c";
console.log(isValidURL(testCase2)); // a4c
var testCase3 = "4bc";
console.log(isValidURL(testCase3)); // 4bc
var testCase4 = "ab4";
console.log(isValidURL(testCase4)); // ab4
var testCase5 = "123"; // fail here
console.log(isValidURL(testCase5));
I had to do something similar in MySQL and the following whilst over simplified seems to have worked for me:
where fieldname regexp ^[a-zA-Z0-9]+$
and fieldname NOT REGEXP ^[0-9]+$
This shows all fields that are alphabetical and alphanumeric but any fields that are just numeric are hidden. This seems to work.
example:
name1 - Displayed
name - Displayed
name2 - Displayed
name3 - Displayed
name4 - Displayed
n4ame - Displayed
324234234 - Not Displayed
The task is pretty simple, but I've not been able to come up with a good solution yet: a string can contain numbers, dashes and pluses, or only numbers.
^[0-9+-]+$
does most of what I need, except when a user enters garbage like "+-+--+"
I've not had luck with regular lookahead, since the dashes and pluses could potentially be anywhere in the string.
Valid strings:
234654
24-3+-2
-234
25485+
Invalid:
++--+
How about this:
([+-]?\d[+-]?)+
which means "one or more digits, each of which can be preceded or followed by an optional plus or minus".
Here's a Python test script:
import re
TESTS = "234654 24-3+-2 -234 25485+ ++--+".split()
for test in TESTS:
print test, ":", re.match(r'([+-]?\d[+-]?)+', test) is not None
which prints this:
234654 : True
24-3+-2 : True
-234 : True
25485+ : True
++--+ : False
How about:
^[0-9+-]*[0-9][0-9+-]*$
This ensures that there is at least one digit somewhere in the string. (It looks like it might have a lot of backtracking, though. But on the other hand it doesn't have a + or * wrapped inside another + or *, which I don't like either.)
^([+-]*[0-9]+[+-]*)+$
Another solution using a positive look behind assertion ensuring there is at leat one number.
^[0-9+-]+$(?<=[0-9][+-]*)
Or using a positive look ahead assertion.
(?=[+-]*[0-9])^[0-9+-]+
I like the
^(?=.*\d)[\d+-]+$
solution, myself. It says exactly what you need without requiring any head-scratching.
I'd do it like this:
^[-+]*\d[\d+-]*$
Fast is good!