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'