1

I am trying to find the correct regular expression that detects string that end with a single underscore, e.g. hello_, this_. So far I have re.match("[aA-zZ](_)", string) but detects strings like, day__, ball__, i.e, with two underscores which i do not want. Any ideas how to get string with a single underscore in the end.

Thanks

Devesh Kumar Singh
  • 20,259
  • 5
  • 21
  • 40
Darkmoor
  • 862
  • 11
  • 29
  • add a `$` at the end – depperm May 31 '19 at 12:39
  • Are you sure that's exactly the regex you're using? Because on my machine, `re.match("[aA-zZ](_)", "day__")` returns None. – Kevin May 31 '19 at 12:40
  • @Kevin Could be a locale issue; `ord("A") < ord("_") < ord("z")`, which means the bracket expression could be matching the first `_`. – chepner May 31 '19 at 12:44
  • @Darkmoor Try a less ambiguous bracket expression like `[a-zA-Z]`. – chepner May 31 '19 at 12:46
  • @chepner, I agree that it's a problem that `[aA-zZ]` can match non-alphanumeric characters such as `[\\]^_` and tilde. But I was more referring to the fact that it matches only one character, and that we're missing a `+` or `*` in the pattern. – Kevin May 31 '19 at 12:47
  • @Kevin Ah, right; I always forget which of `match` and `search` is implicitly anchored to the beginning of the string. – chepner May 31 '19 at 12:48

4 Answers4

6

You may use

re.search(r"(?<!_)_$", s)

See the regex demo. See the regex graph:

enter image description here

Details

  • (?<!_) - a negative lookbehind that makes sure there is no _ immediately the left of the current position
  • _ - an underscore
  • $ - end of string.

Note you need re.search that looks for a match anywhere inside a string, not re.match that matches only at the start of a string.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
3

You may use this regex:

REGEX = re.compile(r'[^_]_$')
REGEX.search(string)`
vurmux
  • 9,420
  • 3
  • 25
  • 45
3

You could also update your character class to use a-z and A-Z and then match a single underscore:

[a-zA-Z]_$

For example using re.search

pattern = "[a-zA-Z]_$"
re.search(pattern, "day__")

Python demo

Note that [aA-zZ] which is the same as [A-z] is different from [a-zA-Z]

The fourth bird
  • 154,723
  • 16
  • 55
  • 70
3

I know you asked for a regex, but this could be done also by simply:

s = "hello__"

s.endswith("_") and not s[:-1].endswith("_")
# False
Lante Dellarovere
  • 1,838
  • 2
  • 7
  • 10