Search code examples
pythonregexstringio

Not able to inline replace using re.sub and io.StringIO in Python


I have written this method in order to replace text in line. It prints the correct text as I want it to be replaced but it is not updating those changes in the file. I am quite new to Python, Could you please help me where I am making a mistake?

def regFind(regx, sub_text, file_name):
  c_file = io.StringIO(file_name)
  for line in c_file:
    match = regx.search(line)
    if match:
      replaced_line = re.sub(regx, sub_text, line)
      line = replaced_line
      #print(line)
    yield line

    regx = re.compile(r'^MYTEXT')
    sub_text = 'NewText'
    a_file = open('file.txt').read()
    for line in regFind(regex, sub_text, a_file):
      print(line)

Solution

  • There is a module in the standard library to help edit files "in-place" -- fileinput. Actually, it does not edit files in-place, instead it writes output to a temporary file, and then renames the temporary file to the original file. This makes it appear as though the file has been edited in-place if everything goes well. If there is an exception, or the program is stopped before the renaming step, then the original file remains untouched.

    import fileinput
    import sys
    import re
    
    screen = sys.stdout
    def regFind(regx, sub_text, filename):
        for line in fileinput.input([filename],
                inplace=True,
                backup='.bak'   # creates a backup of the original file
                ):
            match = regx.search(line)
            if match:
                line = regx.sub(sub_text, line)
            sys.stdout.write(line)
            yield line
    
    # regex = re.compile(r'foo')    
    for line in regFind(regex, sub_text, 'file.txt'):
        screen.write(line+'\n')
    

    fileinput redirects sys.stdout to write to the temporary file, not to the console. So to print to the console, I saved the original sys.stdout to a variable screen and use screen.write instead of print.