Caner
Caner

Reputation: 59328

Regex NOT operator doesn't work

I'm trying to filter files in a folder. I need the files that don't end with ".xml-test". The following regex works as expected (ok1,ok2,ok3 = false, ok4 = true)

String regex = ".+\\.xml\\-test$";
boolean ok1 = Pattern.matches(regex, "database123.xml");
boolean ok2 = Pattern.matches(regex, "database123.sql");
boolean ok3 = Pattern.matches(regex, "log_file012.txt");
boolean ok4 = Pattern.matches(regex, "database.xml-test");

Now I just need to negate it, but it doesn't work for some reason:

String regex = "^(.+\\.xml\\-test)$";

I still get ok1,ok2,ok3 = false, ok4 = true

Any ideas? (As people pointed, this could be done easily without regex. But for arguments sake assume I have to use a single regex pattern and nothing else (ie !Pattern.matches(..); is also not allowed))

Upvotes: 1

Views: 2599

Answers (5)

ridgerunner
ridgerunner

Reputation: 34435

The following Java regex asserts that a string does NOT end with: .xml-test:

String regex = "^(?:(?!\\.xml-test$).)*$";

This regex walks the string one character at a time and asserts that at each and every position the remainder of the string is not .xml-test.

Simple!

Upvotes: 2

MBO
MBO

Reputation: 31025

If you really need to test it with regex, then you should use negative lookbehinds from Pattern class:

String reges = "^.*(?<!\\.xml-test)$"

How it works:

  1. first you match whole string: from start (^) all characters (.*),
  2. you check if what have already matched doesn't have ".xml-test" at end (lookbehind at position you already matched),
  3. you test if it's end of string.

Upvotes: 1

Duncan Jones
Duncan Jones

Reputation: 69410

I think you are looking for:

if (! someString.endsWith(".xml-test")) {
  ...
}

No regular expression required. Throw this into a FilenameFilter as follows:

public accept(File dir, String name) {
  return ! name.endsWith(".xml-test");
}

Upvotes: 5

hoaz
hoaz

Reputation: 10171

^ - is not a negation in regexp, this is a symbol indicating beginning of line you probably need (?!X) X, via zero-width negative lookahead

But I suggest you to use File#listFiles method with FilenameFilter implementation: name.endsWith(".xml-test")

Upvotes: 1

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 727077

The meaning of ^ changes depending on its position in the regexp. When the symbol is inside a character class [] as the first character, it means negation of the character class; when it is outside a character class, it means the beginning of line.

The easiest way to negate a result of a match is to use a positive pattern in regex, and then to add a ! on the Java side to do the negation, like this:

boolean isGoodFile = !Pattern.matches(regex, "database123.xml");

Upvotes: 4

Related Questions