Fillip Peyton
Fillip Peyton

Reputation: 3657

Find string that isn't proceeded by other string

I'm trying to come up with the right Regex for Visual Studio's Find All feature, but am having a really hard time. I have the following strings:

String A:

other.things.go.here.ClientTemplate("#= Namespace.sub.nope.method(data) #");

String B:

other.things.go.here.ClientTemplate("#= Namespace.sub.KeyPhrase.otherMethod(data) #");

String C:

other.things.go.here.ClientTemplate("#= Namespace.sub.something.anything.KeyPhrase.otherMethod(data) #");

This regex should only match String A. Here's what I thought would work:

(ClientTemplate).*~(KeyPhrase)

I need to match a string that has "ClientTemplate" in it and does not proceed with "KeyPhrase".

EDIT: I really screwed this one up. I meant the opposite of what I said:

What regex will match only String A?

Upvotes: 0

Views: 74

Answers (3)

Alan Moore
Alan Moore

Reputation: 75242

EDIT: The question did an about-face on me, so the real answer is at the bottom. I'm leaving the original because it seems less confusing that way and because I think most of the discussion is still helpful even if the regex isn't.


Assuming you're using the regex in pre-2013 Visual Studio (I know you tagged it , but many new users mistakenly add the visual-studio* tags when they're really talking about regexes in their code), your regex seems to work if remove the ~:

(ClientTemplate).*(KeyPhrase)

The ~(...) construct is equivalent to a negative lookahead. You said you want to match lines that do contain the key phrase, so you need to include it in the regex, not exclude it. (That's why I removed the tag.)

However, I would go with something more deterministic, like this:

ClientTemplate\("\#=[^"]*\.KeyPhrase\.[^"]*"\)

I tested this in Visual Studio 2008 and it matches strings B and C, but not A.


EDIT: Turns out this was a negation task after all. Here's a regex that matches string A and doesn't match strings B and C:

<ClientTemplate\("\#= Namespace(\.~(KeyPhrase>):i)*\(data\) \#"\);

:i is roughly equivalent to \w+, the traditional regex for a word in Perl-derived flavors. The lookahead checks that whatever follows the dot is not KeyPhrase before it permits :i> to consume it. The < before ClientTemplate and the > after KeyPhrase and :i are word boundaries; they make sure you're matching only whole words.

Upvotes: 1

repzero
repzero

Reputation: 8412

Consider the following strings in a file named 'my_file'

other.things.go.here.ClientTemplate("#= Namespace.sub.nope.method(data) #");
other.things.go.here.ClientTemplate("#= Namespace.sub.nope.method(data) #");
other.things.go.here.ClientTemplate("#= Namespace.sub.KeyPhrase.otherMethod(data) #");
other.things.go.here.ClientTemplate("#= Namespace.sub.something.anything.KeyPhrase.otherMethod(data) #");
other.things.go.here.ClientTemplate("#= Namespace.sub.something.anything.KeyPhraze.otherMethod(data) #");
other.things.go.here.ClientTemplate("#= Namespace.sub.something.anything.KeyPHRAZE.otherMethod(data) #");
other.things.go.here.ClientTemplate("#= Namespace.sub.something.anything.KeyPHR?ZE.otherMethod(data) #");
other.things.go.here.ClientTemplate("#= Namespace.sub.something.anything.keyphrase.otherMethod(data) #");
other.things.go.here.ClientTemplate("#= Namespace.sub.something.anything.keyphrase.otherMethod(data) #");
other.things.go.here.ClientTemplate("#= Namespace.sub.something.anything.slkjfiowe.otherMethod(data) #");
other.things.go.here.ClientTemplate("#= Namespace.sub.something.anything.dkjsehtw8.otherMethod(data) #");
other.things.go.here.ClientTemplate("#= Namespace.sub.something.anything.11185.otherMethod(data) #");
other.things.go.here.ClientTemplate("#= Namespace.sub.so...................

Command Line

 grep  'other.things.go.here.ClientTemplate("#= Namespace.sub.nope.method(data) #");' '/root/Desktop/my_file' 

Output

other.things.go.here.ClientTemplate("#= Namespace.sub.nope.method(data) #");
other.things.go.here.ClientTemplate("#= Namespace.sub.nope.method(data) #");

The command line print anything that similar to string A.

Regex Pattern can simply be something like this

grep '^other.*go.here.ClientTemplate.*nope.method(data) #");' 'my_file'

Upvotes: 0

Sam Greenhalgh
Sam Greenhalgh

Reputation: 6136

I think you need a pattern like this

ClientTemplate.*KeyPhrase

Demo

Or if you want a string that is NOT proceeded by KeyPhrase you could use a negative lookahead like this

ClientTemplate(?!.*KeyPhrase.*$).*$

Demo

Upvotes: 2

Related Questions