how to replace a line in a file in python - python

I want to replace a string in a file created by my program, But I cant use .replace because It's not in 3.3, How do I replace a line from a file using two inputs(the previous string, replacement), Here Is the code so far:
#Data Creator
def Create(filename):
global UserFile
UserFile = open(str(filename), "w")
global file
file = (filename)
UserFile.close()
#Data Adder
def Add(data):
UserFile = open(file, "a")
UserFile.write(str(data))
UserFile.close()
#Data seeker
def Seek(target):
UserFile = open(file, "r")
UserFile.seek(target)
global postition
position = UserFile.tell(target)
UserFile.close()
return position
#Replace
def Replace(take,put):
UserFile = open(file, "r+")
UserFile.replace(take,put)
UserFile.close
Create("richardlovesdogs.txt")
Add("Richard loves all kinds of dogs including: \nbeagles")
Replace("beagles","pugs")
How do I do this, So that It replaces the word "beagles" with "pugs"?
I'm learning python so any help would be appreciated
Edit :
ive changed the replace code to this
#Replace
def Replace(take,put):
UserFile = open(file, 'r+')
UserFileT = open(file, 'r+')
for line in UserFile:
UserFileT.write(line.replace(take,put))
UserFile.close()
UserFileT.close()
but in the file it outputs:
Richard loves all kinds of dogs including:
pugsles
how do i change it so it outputs only "pugs" not "pugsles"

The first idea which came to my mind is to loop over lines and check if the given line contains the word which you want to replace. Then just use string method - replace. Of course, in the end the result should be put/written to the file.

Perhaps what you were thinking of was the sed command in Unix shell, which will let you replace a specific text in a file with a replacement text from the shell itself.
As others have said, replacing text in Python has always been str.replace().
Hope this helps!

The fastest way to do this, without loading the whole file into memory, is using the file seek, tell and flush. Set your starting pointer to position 0, and increment through the file by len(replacement_word). If the few-byte snippet matches then you set a marker where you are within the file.
After you've scanned the file, you rebuild the file using your markers and joining the segments with your replacement string between them.

Related

How do I remove the "\n" characters when reading my file but deleting one variable then replacing it

I am trying to make a program that reads from a file and deletes one specific line inside of it and then puts all the data stored back to the file separated with a new line. The file uses this format:
Jones|20|20|00
bob|30|19|90
James|40|19|80
So I want to delete (backup contains this and is the line I want to delete)
bob|30|19|90
but the code that I am using takes away the new line and doesnt replace it but when I try to add \n to it the file doesn't want to read as it does this (adds 2 "\n"s):
Jones|20|20|00
James|40|19|80
I am using this code below:
def deleteccsaver(backup):
lockaccount =""
lockaccount = lockaccount.strip("\n")
with open('accounts_project.txt','r+') as f:
newline=[]
for line in f.readlines():
newline.append(line.replace(backup, lockaccount).strip("\n"))
with open('accounts_project.txt','w+') as f:
for line in newline:
f.writelines(line +"\n")
f.close()
resetlogin()
Please help as I dont know how to add the \n back without it appearing as "\n\n"
Without the "\n "it appears as:
Jones|20|20|00James|40|19|80
Any suggestions:
What I am doing here is reading the entire file at once, please don't do this if you have a very very big file. After reading all file contents at once, I am making a list out of it using "\n" as a delimiter. Read about split function in python to know more about it. Then from the list I am replacing the backup with lockaccount, as you have been doing the same, these are the names of variables that you are using, hope I did not confuse between them in this case. Then it will be saved to a new file after adding new line after each element of list, i.e. each line of the previous file. This will cause the result file to have all the contents as previous file, but removing what you wanted to remove. I see that lockaccount is itself an empty string, so adding it might create a newline in your file. In case you dont want lockaccount to replace the backup variable in the file, just remove the backup from the list using contents.remove(backup) instead of contents[contents.index(backup)] == lockaccount keeping the rest of the code same. Hope this explains better.
def deleteccsaver(backup):
lockaccount =""
lockaccount = lockaccount.strip("\n")
with open('accounts_project.txt','r+') as f:
contents = f.read().split("\n")
if backup in contents:
contents[contents.index(backup)] = lockaccount
new_contents = "\n".join(contents)
with open('accounts_project.txt','w+') as f:
f.write(new_contents)
resetlogin()
You are priting a newline character after each element in the list. So, if you replace a line with the empty string, well, you will get an empty line.
Try to simply skip over the line you want to delete:
if line == backup:
contiune
else:
lines.append(...)
PS. There is room for improvment in the code above, but I'm on the phone, I will get back with an edit later if nobody gets ahead of me
You can try to add newline = '\n'.join(newline) after your first for loop and then just write it into the accounts_project.txt file without a loop.
The code should then look like:
def deleteccsaver(backup):
lockaccount =""
lockaccount = lockaccount.strip("\n")
with open('accounts_project.txt','r+') as f:
newline=[]
for line in f.readlines():
newline.append(line.replace(backup, lockaccount).strip("\n"))
newline = '\n'.join(newline)
with open('accounts_project.txt','w+') as f:
f.write(newline)
f.close() # you don't necessarily need it inside a with statement
resetlogin()
Edit:
Above code still results in
Jones|20|20|00
James|40|19|80
as output.
That's because during the replacement loop an empty string will be appended to newline (like newline: ['Jones|20|20|00','','James|40|19|80']) and newline = '\n'.join(newline) will then result in 'Jones|20|20|00\n\nJames|40|19|80'.
A possible fix can be to replace:
for line in f.readlines():
newline.append(line.replace(backup, lockaccount).strip("\n"))
with
for line in f.readlines():
line = line.strip('\n')
if line != backup:
newline.append(line)
def deleteccsaver(backup):
lockaccount =""
lockaccount = lockaccount.strip("\n")
with open('accounts_project.txt','r+') as f:
contents = f.read().split("\n")
if backup in contents:
contents.remove(backup)
new_contents = "\n".join(contents)
with open('accounts_project.txt','w+') as f:
f.write(new_contents)
resetlogin()

replace new line in a different file with an underscore (without using with)

I posted a question yesterday in similar regards to this but didn't quite gauge the response I wanted because I wasn't specific enough. Basically the function takes a .txt file as the argument and returns a string with all \n characters replaced with an '_' on the same line. I want to do this without using WITH. I thought I did this correctly but when I run it and check the file, nothing has changed. Any pointers?
This is what I did:
def one_line(filename):
wordfile = open(filename)
text_str = wordfile.read().replace("\n", "_")
wordfile.close()
return text_str
one_line("words.txt")
but to no avail. I open the text file and it remains the same.
The contents of the textfile are:
I like to eat
pancakes every day
and the output that's supposed to be shown is:
>>> one_line("words.txt")
’I like to eat_pancakes every day_’
The fileinput module in the Python standard library allows you to do this in one fell swoop.
import fileinput
for line in fileinput.input(filename, inplace=True):
line = line.replace('\n', '_')
print(line, end='')
The requirement to avoid a with statement is trivial but rather pointless. Anything which looks like
with open(filename) as handle:
stuff
can simply be rewritten as
try:
handle = open(filename)
stuff
finally:
handle.close()
If you take out the try/finally you have a bug which leaves handle open if an error happens. The purpose of the with context manager for open() is to simplify this common use case.
You are missing some steps. After you obtain the updated string, you need to write it back to the file, example below without using with
def one_line(filename):
wordfile = open(filename)
text_str = wordfile.read().replace("\n", "_")
wordfile.close()
return text_str
def write_line(s):
# Open the file in write mode
wordfile = open("words.txt", 'w')
# Write the updated string to the file
wordfile.write(s)
# Close the file
wordfile.close()
s = one_line("words.txt")
write_line(s)
Or using with
with open("file.txt",'w') as wordfile:
#Write the updated string to the file
wordfile.write(s)
with pathlib you could achieve what you want this way:
from pathlib import Path
path = Path(filename)
contents = path.read_text()
contents = contents.replace("\n", "_")
path.write_text(contents)

Trying to replace a number in text file using regex to find the right line in Python

I am trying to find this explicit sub-string of a specific line in a text file '"swp_pt", "3"' with the double-quotes and all. I want to change the number to any other number, but I need specifically to go to the first integer after the quoted swp_pt variable and change it only. I am still just trying to find the correct swp_pt call in the text file and have not been able to do even that yet.
Here is my code so far:
ddsFile = open('Product_FD_TD_SI_s8p.dds')
for line in ddsFile:
print(line)
marker = re.search('("swp_pt", ")[0-9]+', line)
print(marker)
print(marker.group())
ddsFile.close()
If anyone has a clue how to do this, I would very much appreciate your help.
Mike
Do you really need to do this in Python? sed -i will do what you want and is considerably simpler.
But if you need it, I would do something like:
def replace_swp_pt(line):
regex = r'"swp_pt", "(\d+)"'
replacement = '"swp_pt", "4"'
return re.sub(regex, replacement, line)
def transform_file(file_name, transform_line_func):
with open(file_name, 'r') as f:
# Buffer full contents in memory. This only works if your file
# fits in memory; otherwise you will need to use a temporary file.
file_contents = f.read()
with open(file_name, 'w') as f:
for line in file_contents.split('\n'):
transformed_line = transform_line_func(line)
f.write(transformed_line + '\n')
if __name__ == '__main__':
transform_file('Product_FD_TD_SI_s8p.dds', replace_swp_pt)

Deleting a specific word from a file in python

I am quite new to python and have just started importing text files. I have a text file which contains a list of words, I want to be able to enter a word and this word to be deleted from the text file. Can anyone explain how I can do this?
text_file=open('FILE.txt', 'r')
ListText = text_file.read().split(',')
DeletedWord=input('Enter the word you would like to delete:')
NewList=(ListText.remove(DeletedWord))
I have this so far which takes the file and imports it into a list, I can then delete a word from the new list but want to delete the word also from the text file.
Here's what I would recommend since its fairly simple and I don't think you're concerned with performance.:
f = open("file.txt",'r')
lines = f.readlines()
f.close()
excludedWord = "whatever you want to get rid of"
newLines = []
for line in lines:
newLines.append(' '.join([word for word in line.split() if word != excludedWord]))
f = open("file.txt", 'w')
for line in lines:
f.write("{}\n".format(line))
f.close()
This allows for a line to have multiple words on it, but it will work just as well if there is only one word per line
In response to the updated question:
You cannot directly edit the file (or at least I dont know how), but must instead get all the contents in Python, edit them, and then re-write the file with the altered contents
Another thing to note, lst.remove(item) will throw out the first instance of item in lst, and only the first one. So the second instance of item will be safe from .remove(). This is why my solution uses a list comprehension to exclude all instances of excludedWord from the list. If you really want to use .remove() you can do something like this:
while excludedWord in lst:
lst.remove(excludedWord)
But I would discourage this in favor for the equivalent list comprehension
We can replace strings in files (some imports needed;)):
import os
import sys
import fileinput
for line in fileinput.input('file.txt', inplace=1):
sys.stdout.write(line.replace('old_string', 'new_string'))
Find this (maybe) here: http://effbot.org/librarybook/fileinput.htm
If 'new_string' change to '', then this would be the same as to delete 'old_string'.
So I was trying something similar, here are some points to people whom might end up reading this thread. The only way you can replace the modified contents is by opening the same file in "w" mode. Then python just overwrites the existing file.
I tried this using "re" and sub():
import re
f = open("inputfile.txt", "rt")
inputfilecontents = f.read()
newline = re.sub("trial","",inputfilecontents)
f = open("inputfile.txt","w")
f.write(newline)
#Wnnmaw your code is a little bit wrong there it should go like this
f = open("file.txt",'r')
lines = f.readlines()
f.close()
excludedWord = "whatever you want to get rid of"
newLines = []
for line in newLines:
newLines.append(' '.join([word for word in line.split() if word != excludedWord]))
f = open("file.txt", 'w')
for line in lines:
f.write("{}\n".format(line))
f.close()

How to open a file using the open with statement

I'm looking at how to do file input and output in Python. I've written the following code to read a list of names (one per line) from a file into another file while checking a name against the names in the file and appending text to the occurrences in the file. The code works. Could it be done better?
I'd wanted to use the with open(... statement for both input and output files but can't see how they could be in the same block meaning I'd need to store the names in a temporary location.
def filter(txt, oldfile, newfile):
'''\
Read a list of names from a file line by line into an output file.
If a line begins with a particular name, insert a string of text
after the name before appending the line to the output file.
'''
outfile = open(newfile, 'w')
with open(oldfile, 'r', encoding='utf-8') as infile:
for line in infile:
if line.startswith(txt):
line = line[0:len(txt)] + ' - Truly a great person!\n'
outfile.write(line)
outfile.close()
return # Do I gain anything by including this?
# input the name you want to check against
text = input('Please enter the name of a great person: ')
letsgo = filter(text,'Spanish', 'Spanish2')
Python allows putting multiple open() statements in a single with. You comma-separate them. Your code would then be:
def filter(txt, oldfile, newfile):
'''\
Read a list of names from a file line by line into an output file.
If a line begins with a particular name, insert a string of text
after the name before appending the line to the output file.
'''
with open(newfile, 'w') as outfile, open(oldfile, 'r', encoding='utf-8') as infile:
for line in infile:
if line.startswith(txt):
line = line[0:len(txt)] + ' - Truly a great person!\n'
outfile.write(line)
# input the name you want to check against
text = input('Please enter the name of a great person: ')
letsgo = filter(text,'Spanish', 'Spanish2')
And no, you don't gain anything by putting an explicit return at the end of your function. You can use return to exit early, but you had it at the end, and the function will exit without it. (Of course with functions that return a value, you use the return to specify the value to return.)
Using multiple open() items with with was not supported in Python 2.5 when the with statement was introduced, or in Python 2.6, but it is supported in Python 2.7 and Python 3.1 or newer.
http://docs.python.org/reference/compound_stmts.html#the-with-statement
http://docs.python.org/release/3.1/reference/compound_stmts.html#the-with-statement
If you are writing code that must run in Python 2.5, 2.6 or 3.0, nest the with statements as the other answers suggested or use contextlib.nested.
Use nested blocks like this,
with open(newfile, 'w') as outfile:
with open(oldfile, 'r', encoding='utf-8') as infile:
# your logic goes right here
You can nest your with blocks. Like this:
with open(newfile, 'w') as outfile:
with open(oldfile, 'r', encoding='utf-8') as infile:
for line in infile:
if line.startswith(txt):
line = line[0:len(txt)] + ' - Truly a great person!\n'
outfile.write(line)
This is better than your version because you guarantee that outfile will be closed even if your code encounters exceptions. Obviously you could do that with try/finally, but with is the right way to do this.
Or, as I have just learnt, you can have multiple context managers in a with statement as described by #steveha. That seems to me to be a better option than nesting.
And for your final minor question, the return serves no real purpose. I would remove it.
Sometimes, you might want to open a variable amount of files and treat each one the same, you can do this with contextlib
from contextlib import ExitStack
filenames = [file1.txt, file2.txt, file3.txt]
with open('outfile.txt', 'a') as outfile:
with ExitStack() as stack:
file_pointers = [stack.enter_context(open(file, 'r')) for file in filenames]
for fp in file_pointers:
outfile.write(fp.read())

Categories

Resources