You need to escape your backslash:
p.sub('gray \\1', s)
alternatively you can use a raw string as you already did for the regex:
p.sub(r'gray \1', s)
Answer from mac on Stack OverflowYou need to escape your backslash:
p.sub('gray \\1', s)
alternatively you can use a raw string as you already did for the regex:
p.sub(r'gray \1', s)
As I was looking for a similar answer; but wanting using named groups within the replace, I thought I'd add the code for others:
p = re.compile(r'blue (?P<animal>dog|cat)')
p.sub(r'gray \g<animal>',s)
Python how to replace content in the capture group of regex? - Stack Overflow
regex - Replace named captured groups with arbitrary values in Python - Stack Overflow
regex: Can I use numbered capture group references in strings outside of re.sub?
Python Regex instantly replace groups - Stack Overflow
One solution is to use positive lookahead as follows.
import re
p = re.compile(ur'(\-abc)(?=\.jpg)')
test_str = u"-abc1234567-abc.jpg"
subst = u""
result = re.sub(p, subst, test_str)
OR
You can use two capture groups as follows.
import re
p = re.compile(ur'(\-abc)(\.jpg)')
test_str = u"-abc1234567-abc.jpg"
subst = r"\2"
result = re.sub(p, subst, test_str)
If you only want to remove -abc in only jpg files, you could use:
re.sub(r"-abc\.jpg$", ".jpg", string)
To use your code as close as possible: you should place '()' around the part you want to keep, not the part you want to remove. Then use \g<NUMBER> to select that part of the string. So:
re.sub(r'(.*)-abc(\.jpg)$', '\g<1>\g<2>', string)
This is a completely backwards use of regex. The point of capture groups is to hold text you want to keep, not text you want to replace.
Since you've written your regex the wrong way, you have to do most of the substitution operation manually:
"""
Replaces the text captured by named groups.
"""
def replace_groups(pattern, string, replacements):
pattern = re.compile(pattern)
# create a dict of {group_index: group_name} for use later
groupnames = {index: name for name, index in pattern.groupindex.items()}
def repl(match):
# we have to split the matched text into chunks we want to keep and
# chunks we want to replace
# captured text will be replaced. uncaptured text will be kept.
text = match.group()
chunks = []
lastindex = 0
for i in range(1, pattern.groups+1):
groupname = groupnames.get(i)
if groupname not in replacements:
continue
# keep the text between this match and the last
chunks.append(text[lastindex:match.start(i)])
# then instead of the captured text, insert the replacement text for this group
chunks.append(replacements[groupname])
lastindex = match.end(i)
chunks.append(text[lastindex:])
# join all the junks to obtain the final string with replacements
return ''.join(chunks)
# for each occurence call our custom replacement function
return re.sub(pattern, repl, string)
>>> replace_groups(pattern, s, {'d': 'aaa', 'm': 'bbb', 'Y': 'ccc'})
'monthday=aaa, month=bbb, year=ccc'
You can use string formatting with a regex substitution:
import re
s = 'monthday=1, month=5, year=2018'
s = re.sub('(?<=\=)\d+', '{}', s).format(*['aaa', 'bbb', 'ccc'])
Output:
'monthday=aaa, month=bbb, year=ccc'
Edit: given an arbitrary input string and regex, you can use formatting like so:
input = '2018-12-12'
regex = '((?P<Y>20\d{2})-(?P<m>[0-1]?\d)-(?P<d>\d{2}))'
new_s = re.sub(regex, '{}', input).format(*["aaa", "bbb", "ccc"])
When using re.sub it is possible to use numbered references to refer to each individual match group of the match (as defined by the brackets in the pattern). To showcase:
str1="aaa123-456xxx" pattern = r"(\d\d\d)-(\d\d\d)" x=re.sub(pattern, r"\1ABC\2", str1) print(x) #output: aaa123ABC456xxx
So, in sub() '\1' refers to my first group content '123' and '\2' to the 2nd '456'.
Is there a way to use this syntax outside of re.sub()? Simply to generate new strings from a regular match object? I know I can access the groups via match.groups(n), but I'd much rather simply use '\n'.
Have a look at re.sub:
result = re.sub(r"(\d.*?)\s(\d.*?)", r"\1 \2", string1)
This is Python's regex substitution (replace) function. The replacement string can be filled with so-called backreferences (backslash, group number) which are replaced with what was matched by the groups. Groups are counted the same as by the group(...) function, i.e. starting from 1, from left to right, by opening parentheses.
The accepted answer is perfect. I would add that group reference is probably better achieved by using this syntax:
r"\g<1> \g<2>"
for the replacement string. This way, you work around syntax limitations where a group may be followed by a digit. Again, this is all present in the doc, nothing new, just sometimes difficult to spot at first sight.