The shortest way would probably be to use the fileinput module. For example, the following adds line numbers to a file, in-place:
import fileinput
for line in fileinput.input("test.txt", inplace=True):
print('{} {}'.format(fileinput.filelineno(), line), end='') # for Python 3
# print "%d: %s" % (fileinput.filelineno(), line), # for Python 2
What happens here is:
- The original file is moved to a backup file
- The standard output is redirected to the original file within the loop
- Thus any
printstatements write back into the original file
fileinput has more bells and whistles. For example, it can be used to automatically operate on all files in sys.args[1:], without your having to iterate over them explicitly. Starting with Python 3.2 it also provides a convenient context manager for use in a with statement.
While fileinput is great for throwaway scripts, I would be wary of using it in real code because admittedly it's not very readable or familiar. In real (production) code it's worthwhile to spend just a few more lines of code to make the process explicit and thus make the code readable.
There are two options:
- The file is not overly large, and you can just read it wholly to memory. Then close the file, reopen it in writing mode and write the modified contents back.
- The file is too large to be stored in memory; you can move it over to a temporary file and open that, reading it line by line, writing back into the original file. Note that this requires twice the storage.
The shortest way would probably be to use the fileinput module. For example, the following adds line numbers to a file, in-place:
import fileinput
for line in fileinput.input("test.txt", inplace=True):
print('{} {}'.format(fileinput.filelineno(), line), end='') # for Python 3
# print "%d: %s" % (fileinput.filelineno(), line), # for Python 2
What happens here is:
- The original file is moved to a backup file
- The standard output is redirected to the original file within the loop
- Thus any
printstatements write back into the original file
fileinput has more bells and whistles. For example, it can be used to automatically operate on all files in sys.args[1:], without your having to iterate over them explicitly. Starting with Python 3.2 it also provides a convenient context manager for use in a with statement.
While fileinput is great for throwaway scripts, I would be wary of using it in real code because admittedly it's not very readable or familiar. In real (production) code it's worthwhile to spend just a few more lines of code to make the process explicit and thus make the code readable.
There are two options:
- The file is not overly large, and you can just read it wholly to memory. Then close the file, reopen it in writing mode and write the modified contents back.
- The file is too large to be stored in memory; you can move it over to a temporary file and open that, reading it line by line, writing back into the original file. Note that this requires twice the storage.
I guess something like this should do it. It basically writes the content to a new file and replaces the old file with the new file:
from tempfile import mkstemp
from shutil import move, copymode
from os import fdopen, remove
def replace(file_path, pattern, subst):
#Create temp file
fh, abs_path = mkstemp()
with fdopen(fh,'w') as new_file:
with open(file_path) as old_file:
for line in old_file:
new_file.write(line.replace(pattern, subst))
#Copy the file permissions from the old file to the new file
copymode(file_path, abs_path)
#Remove original file
remove(file_path)
#Move new file
move(abs_path, file_path)
Replace text in a file
Find and replace text
python - Replace string within file contents - Stack Overflow
Replace string in a specific line using python - Stack Overflow
You opened the file with 'w', meaning you are going to write to it. Then you try to read from it. So error.
Try reading from that file, and open another file for writing your output. If needed, when done, delete the first file and rename your output (temp) file to the first file's name.
You must be very new for python ^_^
You can write it like this:
pattern = "Hello"
file = open(r'C:\rtemp\output.txt','r') # open file handle for read
# use r'', you don't need to replace '\' with '/'
# open file handle for write, should give a different file name from previous one
result = open(r'C:\rtemp\output2.txt', 'w')
for line in file:
line = line.strip('\r\n') # it's always a good behave to strip what you read from files
if pattern in line:
line = "Hi" # if match, replace line
result.write(line + '\n') # write every line
file.close() # don't forget to close file handle
result.close()
Homework assignment. I have to open a file from a user input as read only. Close the file. Replace the text from the other user inputs. Open the file to write. Close it again. Then open and print.
file = input('Enter file name:')
old_word = input('Enter a string to be replaced: ')
new_word = input('Enter a string to be added: ')
with open(file, 'r') as infile:
file = infile.read()
infile.close()
with open(file, 'w') as infile:
file = infile.write()
file = file.replace(old_word, new_word)I keep getting an "OSError: [Errno 22]" when it tries to open 'file' again. Any help would be appreciated.
with open("Stud.txt", "rt") as fin:
with open("out.txt", "wt") as fout:
for line in fin:
fout.write(line.replace('A', 'Orange'))
If you'd like to replace the strings in the same file, you probably have to read its contents into a local variable, close it, and re-open it for writing:
I am using the with statement in this example, which closes the file after the with block is terminated - either normally when the last command finishes executing, or by an exception.
def inplace_change(filename, old_string, new_string):
# Safely read the input filename using 'with'
with open(filename) as f:
s = f.read()
if old_string not in s:
print('"{old_string}" not found in {filename}.'.format(**locals()))
return
# Safely write the changed content, if found in the file
with open(filename, 'w') as f:
print('Changing "{old_string}" to "{new_string}" in {filename}'.format(**locals()))
s = s.replace(old_string, new_string)
f.write(s)
It is worth mentioning that if the filenames were different, we could have done this more elegantly with a single with statement.
some notes:
string.replaceandre.subare not in-place so you should be assigning the return value back to your variable.glob.globis better for finding files in a directory matching a defined pattern...- maybe you should be checking if the directory already exists before creating it (I just assumed this, this could not be your desired behavior)
- the
withstatement takes care of closing the file in a safe way. if you don't want to use it you have to usetryfinally. - in your example you where forgetting to put the sufix
*.clean;) - you where not actually writing the files, you could do it like i did in my example or use
fileinputmodule (which until today i did not know)
here's my example:
import re
import os
import glob
source_dir=os.getcwd()
target_dir="clean"
source_files = [fname for fname in glob.glob(os.path.join(source_dir,"*.seq"))]
# check if target directory exists... if not, create it.
if not os.path.exists(target_dir):
os.makedirs(target_dir)
for source_file in source_files:
target_file = os.path.join(target_dir,os.path.basename(source_file)+".clean")
with open(source_file,'r') as sfile:
with open(target_file,'w') as tfile:
lines = sfile.readlines()
# do the replacement in the second line.
# (remember that arrays are zero indexed)
lines[1]=re.sub("K|Y|W|M|R|S",'N',lines[1])
tfile.writelines(lines)
print "DONE"
hope it helps.
You should replace line.replace('M', 'N') with line=line.replace('M', 'N'). replace returns a copy of the original string with the relevant substrings replaced.
An even better way (IMO) is to use re.
import re
line="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
line=re.sub("K|Y|W|M|R|S",'N',line)
print line
I realized that I was wrong by just an indentation. In the code piece 1 mentioned in the question, if I am bringing the 'print line,' from the scope of if i.e. if i outdent it, then this is solved...
As this line was inside the scope of if, hence, only this new_text was being written to the file, and other lines were not being written, and hence the file was left with only the new_text. So, the code piece should be as follow :-
text = "mov9 = " # if any line contains this text, I want to modify the whole line.
new_text = "mov9 = Alice in Wonderland"
x = fileinput.input(files="C:\Users\Admin\Desktop\DeletedMovies.txt", inplace=1)
for line in x:
if text in line:
line = new_text
print line,
x.close()
Also, the second solution given by Rolf of Saxony & the first solution by Padraic Cunningham is somehow similar.
You empty you file because you only write when you find a match, you need to always write the lines:
import sys
text = "mov9 = " # if any line contains this text, I want to modify the whole line.
new_text = "mov9 = Alice in Wonderland\n"
x = fileinput.input(files="C:\Users\Admin\Desktop\DeletedMovies.txt", inplace=1)
for line in x:
if text in line:
line = new_text
sys.stdout.write(line)
If you find a match the line will be set to new_text, so either sys.stdout.write(line) will write the original line or new_text. Also if you actually want to find lines starting with text use if line.startswith(text):
You could also write to a tempfile and replace the original:
from shutil import move
from tempfile import NamedTemporaryFile
text = "mov9 = " # if any line contains this text, I want to modify the whole line.
new_text = "mov9 = Alice in Wonderland\n"
with open("C:\Users\Admin\Desktop\DeletedMovies.txt") as f, NamedTemporaryFile("w", dir=".", delete=False) as tmp:
for line in f:
if text in line:
line = new_text
tmp.write(line)
move(tmp.name, "C:\Users\Admin\Desktop\DeletedMovies.txt")