Regex to match against something that is not a specific substring
Asked Answered
D

4

16

I am looking for a regex that will match a string that starts with one substring and does not end with a certain substring.

Example:

// Updated to be correct, thanks @Apocalisp
^foo.*(?<!bar)$

Should match anything that starts with "foo" and doesn't end with "bar". I know about the [^...] syntax, but I can't find anything that will do that for a string instead of single characters.

I am specifically trying to do this for Java's regex, but I've run into this before so answers for other regex engines would be great too.

Thanks to @Kibbee for verifying that this works in C# as well.

Danieu answered 4/9, 2008 at 1:22 Comment(1)
As I mentioned below - regexp in question for input string "foo123bar" it will match "foo12" - hope this is desired behavior.Pithead
A
9

I think in this case you want negative lookbehind, like so:

foo.*(?<!bar)
Acknowledgment answered 4/9, 2008 at 1:37 Comment(0)
E
1

I'm not familiar with Java regex but documentation for the Pattern Class would suggest you could use (?!X) for a non-capturing zero-width negative lookahead (it looks for something that is not X at that postision, without capturing it as a backreference). So you could do:

foo.*(?!bar) // not correct

Update: Apocalisp's right, you want negative lookbehind. (you're checking that what the .* matches doesn't end with bar)

Egmont answered 4/9, 2008 at 1:33 Comment(1)
Problem with this solution is in the fact that for input string "foo123bar" it will match "foo12" - hope this is desired behavior.Pithead
D
1

Verified @Apocalisp's answer using:

import java.util.regex.Pattern;
public class Test {
  public static void main(String[] args) {
    Pattern p = Pattern.compile("^foo.*(?<!bar)$");
    System.out.println(p.matcher("foobar").matches());
    System.out.println(p.matcher("fooBLAHbar").matches());
    System.out.println(p.matcher("1foo").matches());
    System.out.println(p.matcher("fooBLAH-ar").matches());
    System.out.println(p.matcher("foo").matches());
    System.out.println(p.matcher("foobaz").matches());
  }
}

This output the the right answers:

false
false
false
true
true
true
Danieu answered 4/9, 2008 at 1:46 Comment(0)
E
0

As other commenters said, you need a negative lookahead. In Java you can use this pattern:

"^first_string(?!.?second_string)\\z"
  • ^ - ensures that string starts with first_string
  • \z - ensures that string ends with second_string
  • (?!.?second_string) - means that first_string can't be followed by second_string
Exult answered 4/9, 2008 at 1:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.