Reputation: 346
For example: I have a username string: "[email protected]"
I want to search some password string to make sure it doesn't contain any 3 consecutive letters in the username, e.g.: no "joh", "ohn", "hnw", etc...
I'm aware of a functional way to do this, but is there a way to do this with regex?
Upvotes: 1
Views: 486
Reputation: 33076
Short answer: no, you should do this in your application code by generating all the 3-letter substrings and checking if the password contains any of them.
But if you feel adventurous, you could still summon a bloody regex monster from a 19th century gothic novel to achieve this.
See @sln's and @Floris's answers for that.
My 2cents: that's a very, very bad idea. Regex are great when you have a fixed, regular syntactical structure to recognize, which is not your case.
Upvotes: 4
Reputation: 46435
Heavily inspired by @sln's answer, I would like to offer the following solution:
First - concatenate your user name and password into a single string, separated by a newline (assuming that newline does not otherwise occur in either user name or password; reasonable assumption, I think).
Next, test the resulting string with the following expression:
(?=(...).*\n.*\1)
(See it at work here)
How this works:
(?= ) - positive lookahead: "somewhere we can match this"
(...) - three consecutive characters - 'capture group'. We can refer to these as \1
.*\n - followed by "anything" up to a newline character
.*\1 - followed by "anything" up to a repeat of the first match (the ...)
This is going to try as hard as it can to find a match (that's what regex tries to do). If it succeeds, it means that there was a repeat of three consecutive characters that occurred before the \n
in the part after the \n
. So try to test for the above; if it succeeds, your "rule" was violated.
edit - example of complete (tested, working) Java code:
import java.io.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
class passwordTester
{
public static void main (String[] args) throws java.lang.Exception
{
String username="[email protected]";
String password = "youcantmakethisup";
String input = username + "\n" + password;
System.out.println("testing " + input);
Pattern p = Pattern.compile("(?=(...).*\\n.*\\1)");
Matcher m = p.matcher(input);
if(m.find()) {
System.out.println("the three character sequence '" + input.substring(m.start(), m.start()+3)+ "' was repeated");
}
else System.out.println("the password is good");
}
}
Output:
testing [email protected]
youcantmakethisup
the three character sequence 'ake' was repeated
Upvotes: 1
Reputation:
Capture 3, consume 1
Taking a guess. Catenate username + newline + password.
(atually not a guess)
Context: NO Dot-All
If a match, then error.
# [email protected]\nPassword
# (?=(...)[^\n]*\n(?:(?!\1).)*\1)
(?= # Lookahead assertion start
( . . . ) # Capture 3 non-newline chars
[^\n]* \n # Get up to and the next newline
(?: # Cluster group start
(?! \1 ) # Backref check, not the current 3 char string in front of us
. # This char is ok, consume it in the assertion context
)* # Cluster group end, do 0 to many times
\1 # Here, found a user name sub-string
# in the password, it will match now
) # Lookahead assertion end
Upvotes: 1
Reputation: 17258
I don't think so. Regular expressions don't have "memory" and doing what you want requires memory of previously-matched characters. This might be possible with some of the more evil Perl extensions to regular expressions (inline code?), I'm not sure, but I don't believe this is possible with "pure" regular expressions.
Upvotes: 0