Complementing the other answers, there is another alternative: to check if something nay is something, it is often easier to check if it is, and simply reverse the result. So you could use this regex:
String[] strings = { "4481;77831853;4461;60;CAD;VCP;M3", "4647;86940830;4847;35;FRA;VCP;M3",
"3287;69872804;3297;37;ANT;VCP;JJ", "3827;72247849;3857;38;DEC;VCP;JJ",
"5634;7082850;5634;40;MAR;VCP;PZ", "4362;3882867;4382;41;PAU;VCP;PZ",
"J", "3827;72247849;3857;38;DEC;VCP;AJ", "AJ", "JJ", "M3" };
for(String s : strings) {
System.out.println(s + " = " + (! s.matches("^.*(JJ|M3)$")));
}
The regex is ^.*(JJ|M3)$
.
The markers ^
and $
are the beginning and end of the string, to ensure that it only has that is specified in regex.
.*
is "zero or more characters" (the point is any character - except line breaks) and the quantifier *
means "zero or more occurrences".
JJ|M3
is a alternation, which corresponds toJJ
or M3
.
That is, regex checks whether the string ends with "JJ"
or "M3"
. Therefore, it serves to check what you nay wants. So I reverse the result of method matches
, using !
: if the regex finds a match, it corresponds to what you don’t want, and vice versa.
The exit code above is:
4481;77831853;4461;60;CAD;VCP;M3 = false
4647;86940830;4847;35;FRA;VCP;M3 = false
3287;69872804;3297;37;ANT;VCP;JJ = false
3827;72247849;3857;38;DEC;VCP;JJ = false
5634;7082850;5634;40;MAR;VCP;PZ = true
4362;3882867;4382;41;PAU;VCP;PZ = true
J = true
3827;72247849;3857;38;DEC;VCP;AJ = true
AJ = true
JJ = false
M3 = false
A catch from the previous code is that the method matches
creates a new instance of Pattern
, and how he’s being called into a loop, several instances are created. But since they all use the same regex, you could improve this by using - and reusing - a single instance, creating it outside the loop:
Matcher matcher = Pattern.compile("^.*(JJ|M3)$").matcher("");
for (String s : strings) {
System.out.println(s + " = " + (!matcher.reset(s).matches()));
}
The output is the same as the previous code.
This case can also be solved without regex:
for (String s : strings) {
System.out.println(s + " = " + !(s.endsWith("JJ") || s.endsWith("M3")));
}
The method endsWith
checks if the string ends with certain characters. In this case, just check if it ends with "JJ"
or "M3"
, and deny the result.
+1 for the exit without lookaround! Your answer fits any regex implementation.
– nunks
@nunks.lol if I tell you I never learned the Lookahead, do you believe? I learned regex from grep, sed and vim and I have not yet needed this resource (which does not belong to the regular languages but is called regex)
– Jefferson Quesado
+1 I liked the part
([^J3]|[^JM].|J3|MJ)
, tip you can simplify.|.*
=>.*
– Guilherme Lautert
@Guilhermelautert but is applicable? The
.*
comes concatenated with things at the end, already the.
is the only solitary character. I couldn’t see the simplification, but the moment I get it I add in the answer– Jefferson Quesado
@Jeffersonquesado in fact was my mistake, I could not reduce, I hit the eye
?
and I thought it was for the([^J3]|[^JM].|J3|MJ)
– Guilherme Lautert
@Jeffersonquesado I believe! I also learned regex with sed and use daily in the Solaris shell (it’s not GNU sed, it doesn’t support a lot of things, it has to escape parentheses, etc.). Use lookaround to make life easier in cases of use that support, but tend to forget that it exists most of the time, also for performance issues when the expression will be invoked many times per second (alias, I will add this note in my reply)
– nunks