Java \ Pattern - how to write a pattern that verifies the lack of a string?
I tried from https://docs.oracle.com/javase/1.5.0/docs/api/java/util/regex/Pattern.html.
I have
Pattern PATTERN = Pattern.compile("agg{0}.*");
Matcher m = PATTERN.matcher("agg_0_4_Jul_2010_13_32_53_759_0.csv");
if (m.matches() == true) => true.
I want this to return FALSE - since 开发者_如何学JAVAit does contain agg in the string start. In short - how to verify the lack of substring (in a positive way). Thanks.
Note on original pattern
Your original pattern contains the very peculiar agg{0}
. It needs to be said that this pattern makes no sense. Due to the way precedence between concatenation and repetition, and the fact that {0}
is exactly zero repetition of a pattern, this agg{0}
is simply ag
.
Thus, you get the following:
Pattern PATTERN = Pattern.compile("agg{0}.*");
Matcher m = PATTERN.matcher("aged gouda yum yum!");
System.out.println(m.matches()); // prints "true"
To illustrate how repetition and concatenation interacts, and how sometimes grouping is required, here are some more examples:
System.out.println( "hahaha".matches("ha{3}") ); // prints "false"
System.out.println( "haaa".matches("ha{3}") ); // prints "true"
System.out.println( "hahaha".matches("(ha){3}") ); // prints "true"
References
- regular-expressions.info/Repetition and Round Brackets for Grouping
On negating a matching
The original specification isn't very clear, but here are some basic facts:
- The
String
class has the following simple non-regex methods:boolean startsWith(String prefix)
boolean endsWith(String suffix)
boolean contains(CharSequence s)
- You can negate a boolean using the
!
unaryboolean
complement operator- See also: JLS 15.15.6 Logical Complement Operator !
Here are some simple examples:
System.out.println( "Hello world!".startsWith("Hell") ); // "true"
System.out.println( "By nightfall".endsWith("all") ); // "true"
System.out.println( "Heaven".contains("joy") ); // "false"
System.out.println( ! "Hello world!".startsWith("Hell") ); // "false"
System.out.println( ! "By nightfall".endsWith("all") ); // "false"
System.out.println( ! "Heaven".contains("joy") ); // "true"
On negative lookaround
If the combination of Java's logical complement and String
's non-regex predicate checks don't work for you, you can use negative lookarounds to negate a match on a pattern.
Generally speaking, if you want to negate what ^pattern$
matches, and for some reason you need this done in the regex itself, you can match on ^(?!pattern$).*
instead (perhaps using the single-line mode so the dot matches everything).
Here's an example of matching a*b*
, and negating it using negative lookahead:
String[] tests = {
"aaabb",
"abc",
"bba",
"aaaa",
"bbbbbb",
"what is this?",
};
for (String test : tests) {
System.out.printf("[%s] %s - %s %n",
test,
test.matches("a*b*"),
test.matches("(?!a*b*$).*")
);
}
The above prints:
[aaabb] true - false
[abc] false - true
[bba] false - true
[aaaa] true - false
[bbbbbb] true - false
[what is this?] false - true
References
- regular-expressions.info/Lookarounds
Related questions
- Regex to match 1234, 1324, 2341 (all permutations of {1,2,3,4})
- Checking if every substring of four zeros is followed by at least four ones using regex
- How does the regular expression
(?<=#)[^#]+(?=#)
work? - Why is negation of a regex needed?
Going back to the question
If you insist on using negative lookarounds, then you can use one of these two patterns depending on what you actually need:
^(?!agg).*$
(see on rubular.com)- This matches strings that doesn't start with
agg
- This matches strings that doesn't start with
^(?!.*agg).*$
(see on rubular.com)- This matches strings that doesn't contain
agg
- This matches strings that doesn't contain
Simple alternative:
if (!csv.startsWith("agg") {
// do something
}
Check contains
, it's a method of String
精彩评论