Python regex matching all but last occurrence

To match all but the last dot with a regex:

'\.(?=[^.]*\.)'

Using a lookahead to check that's there another dot after the one we found (the lookahead's not part of the match).


Specific one-char solution

In your current scenario, you may use

text = re.sub(r'\.(?![^.]*$)', '', text)

Here, \.(?![^.]*$) matches a . (with \.) that is not immediately followed ((?!...)) with any 0+ chars other than . (see [^.]*) up to the end of the string ($).

See the regex demo and the Python demo.

Generic solution for 1+ chars

In case you want to replace a . and any more chars you may use a capturing group around a character class with the chars you need to match and add the positive lookahead with .* and a backreference to the captured value.

Say, you need to remove the last occurrence of [, ], ^, \, /, - or . you may use

([][^\\./-])(?=.*\1)

See the regex demo.

Details

  • ([][^\\./-]) - a capturing group matching ], [, ^, \, ., /, - (note the order of these chars is important: - must be at the end, ] must be at the start, ^ should not be at the start and \ must be escaped)
  • (?=.*\1) - a positive lookahead that requires any 0+ chars as many as possible and then the value captured in Group 1.

Python sample code:

import re
text = r"./[\folder]/this-is-a.test/fi^le.cxx.LAST[]^\/-.h"
text = re.sub(r'([][^\\./-])(?=.*\1)', '', text, flags=re.S)
print(text)

Mind the r prefix with string literals. Note that flags=re.S will make . match any linebreak sequences.


Without regular expressions, using str.count and str.replace:

s = "./folder/thisisa.test/file.cxx.h" 
s.replace('.', '', s.count('.')-1)
# '/folder/thisisatest/filecxx.h'