I am attempting to use negative lookbehind to do some matching on strings that will get sent into the system from another system that ours talks to. I have searched for similar questions and I have not been able to solve this based on any previously posted questions.
This works as expected
Pattern pattern = Pattern.compile ("^(?<!SyCs-)([A-Za-z\\s\\d]+)$");
String s = "SyCs-a";
Assert.assertEquals (false, pattern.matcher (s).matches ());
Here's the problem: with the current regex, the following also returns false which makes sense because the '-' (dash) is not part of the allowed values ([A-Za-z\\s\\d]+) .
s = "TyCs-a";
Assert.assertEquals (false, pattern.matcher (s).matches ());
However, I need that to return true but when I add the dash to allowed values, the first String returns true as well.
No dash
Pattern pattern = Pattern.compile ("^(?<!SyCs-)([A-Za-z\\s\\d]+)$");
String s = "SyCs-a";
Assert.assertEquals (false, pattern.matcher (s).matches ());
s = "TyCs-a";
Assert.assertEquals (false, pattern.matcher (s).matches ());
With dash
Pattern pattern = Pattern.compile ("^(?<!SyCs-)([A-Za-z\\s\\d-]+)$");
String s = "SyCs-a";
Assert.assertEquals (true, pattern.matcher (s).matches ());
s = "TyCs-a";
Assert.assertEquals (true, pattern.matcher (s).matches ());
I've tried to make the + not greedy +? but that doesn't change the outcomes at all.
Any suggestions?
Here's the whole set of tests that I am using to verify the regex
@Test
public void testNegativeLookBehind () {
Pattern pattern = Pattern.compile ("^(?<!SyCs-)([A-Za-z\\s\\d]+)$");
String s = "SyCs-a";
Assert.assertEquals (false, pattern.matcher (s).matches ());
s = "SyCs-b";
Assert.assertEquals (false, pattern.matcher (s).matches ());
s = "SyCs-ab";
Assert.assertEquals (false, pattern.matcher (s).matches ());
s = "SyCs-ab1";
Assert.assertEquals (false, pattern.matcher (s).matches ());
s = "SyCs-abZ";
Assert.assertEquals (false, pattern.matcher (s).matches ());
s = "SyCs- abZ";
Assert.assertEquals (false, pattern.matcher (s).matches ());
s = "SyCs ab1";
Assert.assertEquals (true, pattern.matcher (s).matches ());
/*s = "TyCs-a";
Assert.assertEquals (true, pattern.matcher (s).matches ());
s = "SyCr-a";
Assert.assertEquals (true, pattern.matcher (s).matches ());
*/
s = "ab";
Assert.assertEquals (true, pattern.matcher (s).matches ());
s = "sab";
Assert.assertEquals (true, pattern.matcher (s).matches ());
s = "Csab";
Assert.assertEquals (true, pattern.matcher (s).matches ());
s = "yCsab";
Assert.assertEquals (true, pattern.matcher (s).matches ());
s = "SyCsab";
Assert.assertEquals (true, pattern.matcher (s).matches ());
}
The (?<!SyCs-)
is a negative lookbehind that fails the match if there is CyCs-
immediately to the left of the current location. Since the current location is the start of string ( ^
) the lookbehind always returns true and is just useless.
You need to use a lookahead here, not a lookbehind:
String pat = "^(?!SyCs-)[A-Za-z\\s\\d-]+$";
^^^^^^^^^
See the regex demo .
The ^(?!SyCs-)
will check if the string starts with SyCs-
and if it does, the match will be failed.
Note that if you use the pattern with .matches()
method, you may omit ^
and $
anchors in the pattern as that method requires a full string match.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.