68

I'm trying to put together a regex to find when specific words don't exist in a string. Specifically, I want to know when "trunk", "tags" or "branches" doesn't exist (this is for a Subversion pre-commit hook). Based on the Regular expression to match string not containing a word answer I can easily do this for one word using negative look-arounds:

^((?!trunk).)*$

It's the "and" operator I'm struggling with and I can't seem to get combinations including the other two words working.

This is running fine in .NET with a single word:

var exp = new Regex(@"^((?!trunk).)*$");
exp.IsMatch("trunk/blah/blah");

It will return false as it currently stands or true if "trunk" doesn't exist in the path on the second line.

What am I missing here?

Community
  • 1
  • 1
Troy Hunt
  • 20,345
  • 13
  • 96
  • 151

2 Answers2

134

Use a negative look-ahead that asserts the absence of any of the three words somewhere in the input:

^(?!.*(trunk|tags|branches)).*$

I also slightly rearranged your regex to correct minor errors.

Kirk Woll
  • 76,112
  • 22
  • 180
  • 195
Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • 4
    @S.Serp because a look ahead doesn't consume input, you have to leave something outside to actually match on. If you move the `.*` inside the look ahead, you're left with just `^$`, which literally matches nothing (ie a blank), plus a look ahead that matches *something*, which is an impossibility. – Bohemian Mar 01 '17 at 04:58
4

Use a "standard" match and look for !IsMatch

var exp = new Regex(@"trunk|tags|branches");
var result = !exp.IsMatch("trunk/blah/blah");

Why persons love to make their life difficult?

Ah... And remember the ass principle! http://www.codinghorror.com/blog/2008/10/obscenity-filters-bad-idea-or-incredibly-intercoursing-bad-idea.html

So it would be better to write

var exp = new Regex(@"\b(trunk|tags|branches)\b");

But if you really need a negative lookahed expression, and keeping up with the ass principle

var exp = new Regex(@"^(?!.*\b(trunk|tags|branches)\b)";

Tester: http://gskinner.com/RegExr/?2uv1g

I'll note that if you are looking for full paths (words separated by / or \) then

var exp = new Regex(@"^(?!.*(^|\\|/)(trunk|tags|branches)(/|\\|$))";

Tester: http://gskinner.com/RegExr/?2uv1p

xanatos
  • 109,618
  • 12
  • 197
  • 280
  • 1
    Thanks, but unfortunately the constraint in this case requires the work to be done in the regex and I can't control the code outside this to invert the condition. – Troy Hunt Oct 18 '11 at 05:50