tags:

views:

334

answers:

7

I want to write a regex that matches if a string contains XYZ but doesn't contain ABC somewhere before it. So "blah XYZ blah" should match, but "blah ABC blah XYZ blah " should not.

Any ideas? In particular I'm writing the regex in c#, in case there's anything specific to that syntax.

I guess I can use negative lookbehind but haven't used this before...

thanks!

UPDATE: I need a regex as I don't have the ability to modify the code, just some configuration.

UPDATE: Changed as I actually only need to check that ABC doesn't appear before XYZ, I don't need to check if it comes after.

+1  A: 

is there anything wrong with

 string.Contains("XYZ") && !string.contains("ABC")
Jimmy
only if he's working on a homework assignment :D
yx
+1 for simpler approach
Andrew Hare
Sorry, as per the question I need a regex, not just c# code.
Rory
Both sub strings can be within the string, just not in a certain order.
J.J.
a valid point, if you don't NEED regex don't USE regex!
Jeff Atwood
the OP is in the unfortunate situation of NEEDing regex though :(
Jimmy
A: 

Get Expresso. My opinion is that regex's are difficult to master and you'll want to test them thoroughly anyway, so having a tool that helps you with both is the best bet. It's pretty easy to use, there's tutorials out there for it.

Best thing about it: it will generate a chunk of C# code that has your regex in it.

jcollum
A: 

Are you sure this is a regular expression?

A: 

that should do the trick:

^([^(ABC)]*)(XYZ)(.*)$

some examples:

sadsafjaspodsa //False
sadABCdsaABCdsa //False
sadABCdsaABCdsaXYZ //False
sadABCdsaABCdsaXYZaa //False
sadABCddasABCsaXYZdsa //False
sadsaXYZdsa //True
sadsaXYZ //True
empi
sad C dsa XYZ sa // False...
PhiLho
@PhiLho: your case should be false.
J.J.
@J.J.: PhiLho is right, if any of a given characters from ABC appears before XYZ my expression fails
empi
Parentheses, too:sad()dsaXYZasd // False
Alan Moore
+4  A: 
^(?:(?<!ABC).)*XYZ

was fine for my little testset.

PhiLho
“ABCXYZ” would also be matched.
Gumbo
NB: I ended up using "(?si)^(?:(?<!ABC).)*XYZ", where s makes . match newlines and i makes it case-insensitive. The multiline option is important to be off too, so ^ matches start of string instead of start of lines.
Rory
Actually, Alan M's answer without lookbehind is perhaps faster.
Rory
@Rory: don't hesitate to change the accepted answer if one seems better! :-) I admit I don't know if one is faster or not. And it probably doesn't matter, unless you have megabytes of data to check.
PhiLho
A: 

This should work:

^(?:(?!ABC).{3,})?XYZ

And if it also should not appear after XYZ:

^(?:(?!ABC).{3,})?XYZ(?:.{3,}(?<!ABC))?$
Gumbo
+2  A: 

No need for lookbehind:

^(?:(?!ABC).)*XYZ
Alan Moore
This is good - thanks!
Rory