Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Append a suffix to each regex match in python?

Tags:

python

regex

I'm trying to append " Smith" to every name mapped to a spirit animal.

import re

contents = '''
  var cool_spirit_animals = {
    'Abel': 'unicorn',
    'Bob': 'lion'
  };

  var spirit_plants = {
    'Cain': 'venus fly trap'
  };

  var stupid_spirit_animals = {
    'Dan': 'lamprey'
  };

  var spirit_vampires = {
    'Emily': 'Buffy',
    'Fred': 'Dracula'
  };
'''

my_regex = r'(spirit_animals = \{[\n\r\s]*\'\w+)(\': [^\}]*)'
print re.sub(my_regex, r'\1 Smith\2', contents)

but my regex only changes the first name in every animals mapping. The script prints:

  var cool_spirit_animals = {
    'Abel Smith': 'unicorn',
    'Bob': 'lion'
  };

  var spirit_plants = {
    'Cain': 'venus fly trap'
  };

  var stupid_spirit_animals = {
    'Dan Smith': 'lamprey'
  };

  var spirit_vampires = {
    'Emily': 'Buffy',
    'Fred': 'Dracula'
  };

'Bob' didn't change - only 'Abel ' changed. How can I write a regex that appends Smith to all names with spirit animals?

like image 243
John Hoffman Avatar asked Sep 15 '25 20:09

John Hoffman


1 Answers

You can first match the spirit_animal block and then add Smith to the names inside a callback method to the re.sub:

def repl(m):
    return re.sub(r"'(\w+)':", r"'\1 Smith':", m.group())

my_regex = r'spirit_animals\s*=\s*\{[^}]*(?:}(?!;(?:$|\n))[^}]*)*};(?:$|\n)'
print re.sub(my_regex, repl, contents)

See the code demo

The spirit_animals\s*=\s*\{[^}]*(?:}(?!;(?:$|\n))[^}]*)*};(?:$|\n) regex exatracts the spirit_animals block (note it is an unrolled version of (?s)spirit_animals\s*=\s*\{.*?};(?:$|\n) regex). The '(\w+)': matches the names inside that block.

like image 92
Wiktor Stribiżew Avatar answered Sep 18 '25 09:09

Wiktor Stribiżew