无法使用Python中的re.sub和io.StringIO进行内联替换

时间:2022-04-01 20:26:40

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?

我已经编写了这个方法来替换文本。它打印正确的文本,因为我希望它被替换,但它不会更新文件中的这些更改。我是Python的新手,你能不能帮我解决我的错误?

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)

3 个解决方案

#1


1  

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.

标准库中有一个模块可以帮助“就地”编辑文件 - fileinput。实际上,它不会就地编辑文件,而是将输出写入临时文件,然后将临时文件重命名为原始文件。这使得如果一切顺利,就好像文件已经就地编辑了一样。如果存在异常,或者在重命名步骤之前程序已停止,则原始文件保持不变。

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.

fileinput重定向sys.stdout以写入临时文件,而不是控制台。因此,要打印到控制台,我将原始sys.stdout保存到变量屏幕并使用screen.write而不是print。

#2


0  

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:

您需要明确地将更改写入文件。例如,以写入模式('w')打开另一个文件并使用.write方法将数据放入磁盘:

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())

(我还删除了不必要的StringIO并停止使用.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.

附:我写给另一个文件的原因是它更安全。可以在适当的位置更改文件。但如果不够小心,你可能会丢失数据。

#3


0  

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:

此外,如果要替换文件中的文本,则需要复制文件内容,在writemode中打开文件(清空整个文件),然后将修改后的内容写入文件:

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)

#1


1  

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.

标准库中有一个模块可以帮助“就地”编辑文件 - fileinput。实际上,它不会就地编辑文件,而是将输出写入临时文件,然后将临时文件重命名为原始文件。这使得如果一切顺利,就好像文件已经就地编辑了一样。如果存在异常,或者在重命名步骤之前程序已停止,则原始文件保持不变。

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.

fileinput重定向sys.stdout以写入临时文件,而不是控制台。因此,要打印到控制台,我将原始sys.stdout保存到变量屏幕并使用screen.write而不是print。

#2


0  

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:

您需要明确地将更改写入文件。例如,以写入模式('w')打开另一个文件并使用.write方法将数据放入磁盘:

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())

(我还删除了不必要的StringIO并停止使用.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.

附:我写给另一个文件的原因是它更安全。可以在适当的位置更改文件。但如果不够小心,你可能会丢失数据。

#3


0  

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:

此外,如果要替换文件中的文本,则需要复制文件内容,在writemode中打开文件(清空整个文件),然后将修改后的内容写入文件:

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)