Вопрос

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)
Это было полезно?

Решение

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.

Другие советы

You need to write changes to file explicitly. For example, open another file in write mode ('w') and use .write method to put data into disk:

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

f = open('file.txt')
out = open('result.txt', 'w')
for line in regFind(regex, sub_text, f):
  out.write(line)

(I've also removed unnecessary StringIO and stopped loading the whole file into memory with .read())

P.S. The reason I write to another file is that it's safer. It's possible to change the file in place. But you could loose data if not careful enough.

Edit Your code does not work because you dont write those lines into text files.

Also if you want to replace text in file you need to copy contents of file, the open the file in writemode(which empties whole file) and then write modified content to file:

def regFindAndReplace(regx, sub_text, fileName):
    textFile = open(fileName)
    fileContent = textFile.readlines()
    textFile.close()
    writeFile = open(fileName,'w')
    for line in fileContent:
        # strip removes newline character if line has one, you probably wont need it but it does not do harm either
        line = line.strip()
        match = regx.search(line)
        if match:
            replaced_line = re.sub(regx, sub_text, line)
            line = replaced_line
            #print(line)
        writeFile.write(line+'\n')
        #'\n' is way to create newline character because stripped line has it no longer
    writeFile.close()

f = 'MyFile.txt'
regFindAndReplace(regex, sub_text, f)
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top