Regex to match string not ending with pattern
Asked Answered
J

4

12

I try to find a regex that matches the string only if the string does not end with at least three '0' or more. Intuitively, I tried:

.*[^0]{3,}$

But this does not match when there one or two zeroes at the end of the string.

Josephjosepha answered 11/7, 2012 at 11:5 Comment(0)
E
15

If you have to do it without lookbehind assertions (i. e. in JavaScript):

^(?:.{0,2}|.*(?!000).{3})$

Otherwise, use hsz's answer.

Explanation:

^          # Start of string
(?:        # Either match...
 .{0,2}    #  a string of up to two characters
|          # or
 .*        #  any string
 (?!000)   #   (unless followed by three zeroes)
 .{3}      #  followed by three characters
)          # End of alternation
$          # End of string
Economics answered 11/7, 2012 at 12:10 Comment(0)
V
14

You can try using a negative look-behind, i.e.:

(?<!000)$

Tests:

Test  Target String   Matches
1     654153640       Yes
2     5646549800      Yes   
3     848461158000    No
4     84681840000     No
5     35450008748     Yes   

Please keep in mind that negative look-behinds aren't supported in every language, however.

Vessel answered 11/7, 2012 at 11:13 Comment(5)
This won't work in every implementation. It won't work in Javascript, for example. What were you doing it in?Johanajohanan
Sure thing, that it needs tests. However this solution works well and be adapted with language not specified by op.Vessel
Which implementation did you try it in? Looking at the OP's profile he/she seems to be using bash a lot, which doesn't support lookbehinds, so this won't work and can't be adapted.Johanajohanan
If you mention that this is a (negated) lookbehind, that would make it easier for readers to avoid a wild goose chase, by looking up whether their regex environment supports such things.Sudorific
This worked in Visual Studio 2015 Find in Files: "do_(\w+|[\w-[0-9]]\w*(?<!Desc|Msg))\b" finds all C++ identifiers that do not end with Desc or Msg.Buffington
O
3

What wrong with the no-look-behind, more general-purpose ^(.(?!.*0{3,}$))*$?

The general pattern is ^(.(?!.* + not-ending-with-pattern + $))*$. You don't have to reverse engineer the state machine like Tim's answer does; you just insert the pattern you don't want to match at the end.

Onida answered 29/1, 2016 at 16:9 Comment(0)
J
1

This is one of those things that RegExes aren't that great at, because the string isn't very regular (whatever that means). The only way I could come up with was to give it every possibility.

.*[^0]..$|.*.[^0].$|.*..[^0]$

which simplifies to

.*([^0]|[^0].|[^0]..)$

That's fine if you only want strings not ending in three 0s, but strings not ending in ten 0s would be long. But thankfully, this string is a bit more regular than some of these sorts of combinations, and you can simplify it further.

.*[^0].{0,2}$
Johanajohanan answered 11/7, 2012 at 11:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.