My application has a feature to check password. I need to get this scenario:
password length 10 ~ 32 .
It has to be a combination of either:
character and numbers
characters and special characters
numbers and special characters
Current code in application:
private boolean isSpecialMixedText(String password)
{
String number = "[0-9]";
String english = "[a-zA-Z]";
String special = "[!##\\$%^&*()~`\\-=_+\\[\\]{}|:\\\";',\\./<>?£¥\\\\]";
Pattern numberPattern = Pattern.compile(number);
Matcher numberMatcher = numberPattern.matcher(password);
Pattern englishPattern = Pattern.compile(english);
Matcher englishMatcher = englishPattern.matcher(password);
Pattern specialPattern = Pattern.compile(special);
Matcher specialMatcher = specialPattern.matcher(password);
return numberMatcher.find() && englishMatcher.find() || specialMatcher.find();
}
Please help me get the combination working
Actually, the regexes look fine. The problem is in this statement:
return numberMatcher.find() && englishMatcher.find() ||
specialMatcher.find();
It actually needs to be something like this:
boolean n = numberMatcher.find();
boolean e = englishMatcher.find();
boolean s = specialMatcher.find();
return (n && e) || (n && s) || (e && s);
And I agree with #adelphus' comment. Your rules for deciding what passwords are acceptable are very English-language-centric.
In my opinion your logic is wrong because you look for combination (so only these characters allowed) of: characters and numbers OR characters and special characters OR numbers and special characters. However with pair of matches like: [0-9] and [a-zA-Z] you are actually looking for a String with some digits and some letter, but it could be also 123ABC#$%#$%$#%#$ (because it has letters and digits).
What you need is something to check, if given string is composed ONLY of of allowed combination of characters. I think you can use one regex here (not too elegant, but effective) like:
^(?:((?=.*[A-Za-z].*)(?=.*[0-9].*)[A-Za-z0-9]{10,32})|((?=.*[-!##\\$%^&*()~`\=_+\[\]{}|:\";',.\/<>?£¥\\].*)(?=.*[0-9].*)[0-9-!##\\$%^&*()~`\=_+\[\]{}|:\";',.\/<>?£¥\\]{10,32})|((?=.*[-!##\\$%^&*()~`\=_+\[\]{}|:\";',.\/<>?£¥\\].*)(?=.*[A-Za-z].*)[-A-Za-z!##\\$%^&*()~`\=_+\[\]{}|:\";',.\/<>?£¥\\]{10,32}))$
DEMO - it show valid and invalid matches.
This is quite long regex, but mainly because of you special character class. This regular expression is composed of three parts with similar structure:
positive lookagead for required characters + character class of
allowed characters
On an example:
(?=.*[A-Za-z].*)(?=.*[0-9].*)[A-Za-z0-9]{10,32}
means that string need to have:
(?=.*[A-Za-z].*) - at least one letter (positive lookahead for letter which could be surrounded by other characters),
(?=.*[0-9].*) - at least one number (positive lookahead for digit which could be surrounded by other characters)
[A-Za-z0-9]{10,32} - from 10 to 32 letters or digits,
in effect, the given password need to have 10 to 32 characters, but both letters and digits, proportion is not important.
Whats more, the ^ at beginning and $ in the end ensure that the whole examined string has such composition.
Also I would agree with others, it is not best idea to restrict allowed character in password like that, but it is your decision.
Related
For example:
public static void smallestWord() {
String smallestWord = "~";
List<String> words = new ArrayList<>();
words.add("dba");
words.add("dba");
words.add("eba");
words.add("dca");
words.add("eca");
for (String word : words) {
if (word.compareTo(smallestWord) < 0) {
smallestWord = word;
}
}
}
It returns dba as smallest word which is correct, but I initialized smallestWord as ~ initially, if I leave it as empty or . I do not get the correct answer. What value does ~ hold in Java lexicography?
All characters in Java are compared by their Unicode codepoint. ~ is U+007E (126) in Unicode, which as larger than all the standard ASCII Latin characters, but less than characters from all other scripts, or accented Latin characters. For more detailed information on how strings are compared, you can read the String.compareTo JavaDoc.
What you want to do is probably rather something like this:
public static void smallestWord() {
String smallestWord = null;
List<String> words = new ArrayList<>();
words.add("dba");
words.add("dba");
words.add("eba");
words.add("dca");
words.add("eca");
for (String word : words) {
if ((smallestWord == null) || (word.compareTo(smallestWord) < 0)) {
smallestWord = word;
}
}
}
Or, alternatively, use the standard library:
Collections.min(words);
As others have pointed out '~' is an ASCII character / Unicode codepoint that is larger than all ASCII letters; i.e. upper and lowercase 'A' through 'Z'.
Therefore, according to the specification1 of the String class, "~" comes after any English word.
However, the '~' codepoint is NOT less than accented letters and letters in non-latin alphabets. So the "~" trick won't work with Cyrillic or Hindi. And if you can think of a French / German / Portuguese / etc word that has an accented first letter, it won't work in those languages either.
And it won't work with Emojis either.
In short, that code using "~" as in your example won't work in internationalized contexts.
You could use null as per #Dolda2000's answer, or you could use "\u10ffff".
(\u10ffff is the largest possible Unicode codepoint. However that approach is not entirely fool-proof either. There are legal Java strings that are larger than "\u10ffff"; e.g. "\u10ffffZZZZ". Unfortunately, the largest possible string value cannot be written as a string literal, and its representation is ridiculously large - roughly 2^31 bytes!)
1 - The ordering of strings is based on the ordering of UTF-16 code units rather than Unicode codepoints. But for well-formed strings there is no difference in the two ways of thinking about it.
compareTo works unicode character value, ~ has unicode value greater than the alphabets so it works while space and dot has unicode value less than alphabets so it consider them as small and print the same.
i want to have regular expression to check input character as a-z and 0-9 but i do not want to allow input as just numeric value at all ( must be have at least one alphabetic character)
for example :
413123123123131
not allowed but if have just only one alphabetic character in any place of phrase it's ok
i trying to define correct Regex for that and at final i raised to
[0-9]*[a-z].*
but in now i confused how to defined {x,y} length of phrase i want to have {9,31} but after last * i can not to have length block too i trying to define group but unlucky and not worked
tested at https://www.debuggex.com/
how can i to add it ??
What you seek is
String regex = "(?=.{9,31}$)\\p{Alnum}*\\p{Alpha}\\p{Alnum}*";
Use it with String#matches() / Pattern#matches() method to require a full string match:
if (s.matches(regex)) {
return true;
}
Details
^ - implicit in matches() - matches the start of string
(?=.{9,31}$) - a positive lookahead that requires 9 to 31 any chars other than line break chars from the start to end of the string
\\p{Alnum}* - 0 or more alphanumeric chars
\\p{Alpha} - an ASCII letter
\\p{Alnum}* - 0 or more alphanumeric chars
Java demo:
String lines[] = {"413123123123131", "4131231231231a"};
Pattern p = Pattern.compile("(?=.{9,31}$)\\p{Alnum}*\\p{Alpha}\\p{Alnum}*");
for(String line : lines)
{
Matcher m = p.matcher(line);
if(m.matches()) {
System.out.println(line + ": MATCH");
} else {
System.out.println(line + ": NO MATCH");
}
}
Output:
413123123123131: NO MATCH
4131231231231a: MATCH
This might be what you are looking for.
[0-9a-zA-Z]*[a-zA-Z][0-9a-zA-Z]*
To help explain it, think of the middle term as your one required character and the outer terms as any number of alpha numeric characters.
Edit: to restrict the length of the string as a whole you may have to check that manually after matching. ie.
if (str.length > 9 && str.length < 31)
Wiktor does provide a solution that involves more regex, please look at his for a better regex pattern
Try this Regex:
^(?:(?=[a-z])[a-z0-9]{9,31}|(?=\d.*[a-z])[a-z0-9]{9,31})$
OR a bit shorter form:
^(?:(?=[a-z])|(?=\d.*[a-z]))[a-z0-9]{9,31}$
Demo
Explanation(for the 1st regex):
^ - position before the start of the string
(?=[a-z])[a-z0-9]{9,31} means If the string starts with a letter, then match Letters and digits. minimum 9 and maximum 31
| - OR
(?=\d.*[a-z])[a-z0-9]{9,31} means If the string starts with a digit followed by a letter somewhere in the string, then match letters and digits. Minimum 9 and Maximum 31. This also ensures that If the string starts with a digit and if there is no letter anywhere in the string, there won't be any match
$ - position after the last literal of the string
OUTPUT:
413123123123131 NO MATCH(no alphabets)
kjkhsjkf989089054835werewrew65 MATCH
kdfgfd4374985794379857984379857weorjijuiower NO MATCH(length more than 31)
9087erkjfg9080980984590p465467 MATCH
4131231231231a MATCH
kjdfg34 NO MATCH(Length less than 9)
Here's the regex:
[a-zA-Z\d]*[a-zA-Z][a-zA-Z\d]*
The trick here is to have something that is not optional. The leading and trailing [a-zA-Z\d] has a * quantifier, so they are optional. But the [a-zA-Z] in the middle there is not optional. The string must have a character that matches [a-zA-Z] in order to be matched.
However, you need to check the length of the string with length afterwards and not with regex. I can't think of any way how you can do this in regex.
Actually, I think you can do this regexless pretty easily:
private static boolean matches(String input) {
for (int i = 0 ; i < input.length() ; i++) {
if (Character.isLetter(input.charAt(i))) {
return input.length() >= 9 && input.length() <= 31;
}
}
return false;
}
I am not quite sure of what is the correct regex for the period in Java. Here are some of my attempts. Sadly, they all meant any character.
String regex = "[0-9]*[.]?[0-9]*";
String regex = "[0-9]*['.']?[0-9]*";
String regex = "[0-9]*["."]?[0-9]*";
String regex = "[0-9]*[\.]?[0-9]*";
String regex = "[0-9]*[\\.]?[0-9]*";
String regex = "[0-9]*.?[0-9]*";
String regex = "[0-9]*\.?[0-9]*";
String regex = "[0-9]*\\.?[0-9]*";
But what I want is the actual "." character itself. Anyone have an idea?
What I'm trying to do actually is to write out the regex for a non-negative real number (decimals allowed). So the possibilities are: 12.2, 3.7, 2., 0.3, .89, 19
String regex = "[0-9]*['.']?[0-9]*";
Pattern pattern = Pattern.compile(regex);
String x = "5p4";
Matcher matcher = pattern.matcher(x);
System.out.println(matcher.find());
The last line is supposed to print false but prints true anyway. I think my regex is wrong though.
Update
To match non negative decimal number you need this regex:
^\d*\.\d+|\d+\.\d*$
or in java syntax : "^\\d*\\.\\d+|\\d+\\.\\d*$"
String regex = "^\\d*\\.\\d+|\\d+\\.\\d*$"
String string = "123.43253";
if(string.matches(regex))
System.out.println("true");
else
System.out.println("false");
Explanation for your original regex attempts:
[0-9]*\.?[0-9]*
with java escape it becomes :
"[0-9]*\\.?[0-9]*";
if you need to make the dot as mandatory you remove the ? mark:
[0-9]*\.[0-9]*
but this will accept just a dot without any number as well... So, if you want the validation to consider number as mandatory you use + ( which means one or more) instead of *(which means zero or more). That case it becomes:
[0-9]+\.[0-9]+
If you on Kotlin, use ktx:
fun String.findDecimalDigits() =
Pattern.compile("^[0-9]*\\.?[0-9]*").matcher(this).run { if (find()) group() else "" }!!
Your initial understanding was probably right, but you were being thrown because when using matcher.find(), your regex will find the first valid match within the string, and all of your examples would match a zero-length string.
I would suggest "^([0-9]+\\.?[0-9]*|\\.[0-9]+)$"
There are actually 2 ways to match a literal .. One is using backslash-escaping like you do there \\., and the other way is to enclose it inside a character class or the square brackets like [.]. Most of the special characters become literal characters inside the square brackets including .. So use \\. shows your intention clearer than [.] if all you want is to match a literal dot .. Use [] if you need to match multiple things which represents match this or that for example this regex [\\d.] means match a single digit or a literal dot
I have tested all the cases.
public static boolean isDecimal(String input) {
return Pattern.matches("^[-+]?\\d*[.]?\\d+|^[-+]?\\d+[.]?\\d*", input);
}
I am working on password enhancement and client wants a password that does not have consecutive letters ie: 123, 234.
I have figured out that you can declare strings that you want to match in regex like (012|123|234|345|456|567|678|789|890) and made it as the regex sequence.
This sequence is separated from the other sequences for easy reading.
The problem is, I cannot match the password with the pattern even if I included 123 or 234 in the password character.
I've read that regex cannot detect 123 as consecutive numbers, but as a string, can it do so?
If you have a limited sequence of characters following one another you can use a Pattern, .find() on a matcher on your input and just invert the test:
// Only the alternation is needed, no need for the capture
private static final Pattern PATTERN
= Pattern.compile("012|123|234|345|456|567|678|789|890");
// ...
if (PATTERN.matcher(input).find())
// fail: illegal sequence found
But if you want to detect that code points follow one another you have to use character functions:
final CharBuffer buf = CharBuffer.wrap(input);
int maxSuccessive = 0;
int successive = 0;
char prev = buf.get();
char next;
while (buf.hasRemaining()) {
next = buf.get();
if (next - prev == 1)
successive++;
else {
maxSuccessive = Math.max(maxSuccessive, successive);
successive = 0;
}
prev = next;
}
// test maxSuccessive
Note however that this will test successive characters according to "canonical ordering", not collation. In some locales, for instance, what is immediately after a is A, not b.
More generally, if you want to test for password requirements and constraint evolves, you are better off splitting things a bit. For instance, consider this:
public interface PasswordChecker
{
boolean isValid(final String passwd);
}
Implement this interface for each of your checks (for instance, length, presence/absence of certain characters, etc), and when you do check for a password, have a List of checkers; the password is invalid if one checker returns false:
private final List<PasswordChecker> checkers = ...;
// then
for (final PasswordChecker checker: checkers)
if (!checker.isValid(passwd))
return false;
return true;
If you use Guava, you can forget about PasswordChecker and use Predicate<String>.
If you're only dealing with these strings of digits that you want to exclude, you can achieve this using a negative lookahead assertion:
^(?!.*(012|123|234|345|456|567|678|789|890))<regex>
where <regex> is the actual regex you're using to match the password, and (?!...) is the lookahead that asserts it's impossible to match that string in your regex.
If you're asking about any increasing sequence of characters, then regex is not the right tool for this. You would have to do that programmatically.
I have a String, where only numbers and none, one or more percentages are allowed
so my regex would be: [\d+%], you can test it here
for java i have to transform it,
public static final String regex = "[\\d+\\%]";
and to test it i use this function
public static final String regex = "[\\d+\\%]";
public boolean validate(String myString){
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(myString);
if (!matcher.matches()) {
return false;
}else{
return true;
}
}
The regular expression is not working, also if i use
public static final String regex = "[\\d+%]";
Is there any good online tool for escaping a long regular expression for java?
A more advanced question:
the % should be only allowed if a minimum of one digit is in the String, only a % shouldn't be allowed! And: numbers without a % are only allowed if the number of digits is exactly 8, not less (means: 1234567 is bad, but 12345678 is good)
Testcases:
Bad: %, (empty string), 23b, -1, 7.5, %5a, 1, 1234567
Good: 12345678, 23%, 1%53%53, %7
I have a String, where only numbers and none, one or more percentages are allowed so my regex would be: [\d+%]
Actually, that matches ONE character which may be a digit, a + or a %.
To match what you have described in words, you need something like this:
[\d%]*\d[\d%]*
which matches a string containing at least one digit with optional percent signs. Note that the % character is not a meta-character and hence doesn't need to be escaped in the regex. It will match all of the following:
0
00
%0
0%0
00%
0%0%0
0%%0
and so on, but not just % or any string that contains characters other than digits or % characterss.
Is there any good online tool for escaping a long regular expression for java?
I'm not aware of one. But escaping wasn't the reason your regex wasn't working.
A more advanced question: the % should be only allowed if a minimum of one digit is in the String, only a % shouldn't be allowed!
I think my regex above does that. And for the record, here is what it looks like as a Java String literal:
"[\\d%]*\\d[\\d%]*"
Unless you have TAB, NL, CR, etc characters in the regex , it is sufficient to just replace each individual \ with \\.