How can I write a regex that finds everything but 4 digit numbers like 2000 or 1990 or 1234?

Viewed 67

I have a text like this:

Film_relase_date:1970_films_by_20th_Century_Fox

I would like to create a regex that matches all text except 1970, resulting in:

Film_relase_date:_films_by_20th_Century_Fox

I tried with the regex:

[^\d{4}]

But this regex returns:

Film_relase_date:_films_by_th_Century_Fox

And therefore also excludes the 20 which instead I would like to be matched. How can I improve the regex?

EDIT: I want to use this regex to do something like:

x = 'Film_relase_date: 1970_films_by_20th_Century_Fox'

REPLACE (x, "Anything that is not a 4-digit number", "Non-Space") = 1970
2 Answers

Remember that {4} is supposed to be added after the character class, not inside.

Anyway, if you want to match "all text except 1970", you can use the following regex:

([^\d]|(?<!\d)\d(?!\d{3}(?!\d))\d*)?

see demo.

This regex matches:

  • a non-digit character or
  • a digit char that is nor preceded by another digit and it is not followeb by exactly 3 digits

If you want to match all except 4 digits, I would suggest an unrolled version matching either 1-3 or 5 digits asserting not followed by a digit to prevent consecutive matching digits.

If you don't want to cross newlines, you could use [^\d\r\n] instead of \D

\D+(?:(?:\d{1,3}|\d{5,})(?!\d)\D*)*

Explanation

  • \D+ Match 1+ non digits
  • (?: Non capture group
    • (?:\d{1,3}|\d{5,}) Match either 1-3 or 5 or more digits
  • (?!\d)\D* Negative lookahead, assert not a digit directly to the right followed by matching optional non digits
  • )* Close the non capture group and repeat 0+ times

Regex demo

Note that if you want to match 4 digits only, you could perhaps extract the 4 digits using (?<!\d)\d{4}(?!\d) instead of replacing with an empty string.

See another regex demo

Related