You could use re.sub
with a callback which returns matchobj.lastgroup
:
import re
s = "the blue dog and blue cat wore 7 blue hats 9 days ago"
p = re.compile(r'blue (?P<animal>dog|cat)|(?P<numberBelowSeven>[0-7])|(?P<numberNotSeven>[8-9])')
def callback(matchobj):
return matchobj.lastgroup
result = p.sub(callback, s)
print(result)
yields
the animal and animal wore numberBelowSeven blue hats numberNotSeven days ago
Note that if you are using Pandas, you could use Series.str.replace
:
import pandas as pd
def callback(matchobj):
return matchobj.lastgroup
df = pd.DataFrame({'foo':["the blue dog", "and blue cat wore 7 blue", "hats 9",
"days ago"]})
pat = r'blue (?P<animal>dog|cat)|(?P<numberBelowSeven>[0-7])|(?P<numberNotSeven>[8-9])'
df['result'] = df['foo'].str.replace(pat, callback)
print(df)
yields
foo result
0 the blue dog the animal
1 and blue cat wore 7 blue and animal wore numberBelowSeven blue
2 hats 9 hats numberNotSeven
3 days ago days ago
If you have nested named groups, you may need a more complicated callback which iterates through matchobj.groupdict().items()
to collect all the relevant group names:
import pandas as pd
def callback(matchobj):
names = [groupname for groupname, matchstr in matchobj.groupdict().items()
if matchstr is not None]
names = sorted(names, key=lambda name: matchobj.span(name))
result = ' '.join(names)
return result
df = pd.DataFrame({'foo':["the blue dog", "and blue cat wore 7 blue", "hats 9",
"days ago"]})
pat=r'blue (?P<animal>dog|cat)|(?P<numberItem>(?P<numberBelowSeven>[0-7])|(?P<numberNotSeven>[8-9]))'
# pat=r'(?P<someItem>blue (?P<animal>dog|cat)|(?P<numberBelowSeven>[0-7])|(?P<numberNotSeven>[8-9]))'
df['result'] = df['foo'].str.replace(pat, callback)
print(df)
yields
foo result
0 the blue dog the animal
1 and blue cat wore 7 blue and animal wore numberItem numberBelowSeven blue
2 hats 9 hats numberItem numberNotSeven
3 days ago days ago