316

Is there an NOT operator in Regexes? Like in that string : "(2001) (asdf) (dasd1123_asd 21.01.2011 zqge)(dzqge) name (20019)"

I want to delete all \([0-9a-zA-z _\.\-:]*\) but not the one where it is a year: (2001).

So what the regex should return must be: (2001) name.

NOTE: something like \((?![\d]){4}[0-9a-zA-z _\.\-:]*\) does not work for me (the (20019) somehow also matches...)

1
  • 1
    There is a String like above and I want to regex it up, that the result of the regex is: (2001) name. Commented Sep 6, 2011 at 9:01

4 Answers 4

491

Not quite, although generally you can usually use some workaround on one of the forms

  • [^abc], which is character by character not a or b or c,
  • or negative lookahead: a(?!b), which is a not followed by b
  • or negative lookbehind: (?<!a)b, which is b not preceeded by a
Sign up to request clarification or add additional context in comments.

5 Comments

Yep, I think negative look-behind is (?<!a)b -- reference: regular-expressions.info/lookaround.html
But [^abc] should mean not a or b or c, not "not the string abc".
Thanks. %[^sdf] or %(?!(s|d|f)) equals to "contains %", but not "%s", "%d" or "%f".
negative look(ahead|behind) also allows for easy negation of multiple letters, e.g. you(?!tube) or (?<!docker)hub
a(?!b) (a not followed by b) is brillant. Best answer. 👍
207

No, there's no direct not operator. At least not the way you hope for.

You can use a zero-width negative lookahead, however:

\((?!2001)[0-9a-zA-z _\.\-:]*\)

The (?!...) part means "only match if the text following (hence: lookahead) this doesn't (hence: negative) match this. But it doesn't actually consume the characters it matches (hence: zero-width).

There are actually 4 combinations of lookarounds with 2 axes:

  • lookbehind / lookahead : specifies if the characters before or after the point are considered
  • positive / negative : specifies if the characters must match or must not match.

7 Comments

Thank you the ?! is what I was suggesting too, but anyway if I use \((?![\d]{4})[0-9a-zA-z _\.\-:]+\) there is still (20019) in it
In the edit of your question you put the {4} outside the lookahead and in this comment you put it inside: which one did you try? Also: if you want (20019) to match, then you must add the \) inside your lookahead: \((?![\d]{4}\))[0-9a-zA-z _\.\-:]+\)
With the regex above in your comment, it works. But I don't understand that... I don't get why you escape the following part \((?![\d]{4} -->\)<--)[0-9a-zA-z _\.\-:]+\) Then there is a bracket not closed, isn't it?
I escape the closing parenthesis ) because I want to match the literal character ) (just as you do at the very beginning and the very end of your regex!). Then after I matched that, I end the lookahead by using an unescaped ).
Got it. I was a little bit confused by all that characters. Thank you.
|
1

You could capture the (2001) part and replace the rest with nothing.

public static string extractYearString(string input) {
    return input.replaceAll(".*\(([0-9]{4})\).*", "$1");
}

var subject = "(2001) (asdf) (dasd1123_asd 21.01.2011 zqge)(dzqge) name (20019)";
var result = extractYearString(subject);
System.out.println(result); // <-- "2001"

.*\(([0-9]{4})\).* means

  • .* match anything
  • \( match a ( character
  • ( begin capture
  • [0-9]{4} any single digit four times
  • ) end capture
  • \) match a ) character
  • .* anything (rest of string)

3 Comments

Use .replace() with a global regex flag, since .replaceAll() is not supported by a lot of browsers and also node.
@lorikku java != javascript
@zyexal Oh oops! I didn't realise it was java haha, my bad!
1

Here is an alternative:

(\(\d{4}\))((?:\s*\([0-9a-zA-z _\.\-:]*\))*)([^()]*)(( ?\([0-9a-zA-z _\.\-:]*\))*)

Repetitive patterns are embedded in a single group with this construction, where the inner group is not a capturing one: ((:?pattern)*), which enable to have control on the group numbers of interrest.

Then you get what you want with: \1\3

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.