I am looking to replace one text file with the contents of another if they are not the same.
Whenever I run this script, "['" and "']" are added on to the old_text.txt file, which means it will never match with new_text.txt file.
How do I remove these characters so the .txt files have the exact same contents after running this script?
old_text = open('old_text.txt', 'r+')
new_text = open('new_text.txt', 'r+')
old_text_compare = str(old_text.readlines())
new_text_compare = str(new_text.readlines())
if old_text_compare != new_text_compare:
print("difference")
old_text = open('old_text.txt', 'w')
old_text.write(str(new_text_compare))
else:
print("no difference")
If you want to compare file contents directly, use .read() rather than .readlines()
with open('old_text.txt', 'r+') as f1, open('new_text.txt', 'r+') as f2:
old = f1.read()
new = f2.read()
if old != new:
with open('new_text.txt', 'w') as f1:
f1.write(old)
else:
print("no difference")
You want to compare the list of lines directly, like so:
if old_text.readlines() != new_text.readlines():
...
def getlink():
with open('findlink.txt') as infile, open('extractlink.txt', 'w') as outfile:
copy = False
for line in infile:
if "](" in line.strip():
copy = True
if copy:
outfile.write(line)
if ")" in line.strip():
copy = False
print("extractlink written.")
def part3():
with open ('findlink.txt', 'w') as findlink:
findlink.write("[Testing](Test)")
print("findlink written and closed.")
getlink()
def run_bot():
getlink() #Already have findlink.txt written
When part3() is activated, the text is written to findlink.txt as expected, but when getlink() is activated, the extractlink.txt is never written to.
I've gathered my current code from a post back in 2013/2016, does anyone have any ideas why this may not be working?
The current goal is to have "Test" from findlink copied to extractlink.txt, not the entire line.
Someone edited your post to fix this, but you should understand that it is unnecessary to explicitly close a file when using a "with" statement AKA a context manager, because they handle this automatically for you.
A simple parser :
def getlink():
with open('findlink.txt') as infile, open('extractlink.txt', 'w') as outfile:
for line in infile:
begin = line.find("](")+2
end = line.find(")")
if 0 <= begin < end:
outfile.write(line[begin:end]+'\n')
According to this [tutorial][1] https://www.tutorialspoint.com/python/string_strip.htm
line.strip("text") removes text from the string.
So when you call line.strip() == "](" you are comparing line.strip("") with "](" which is always false unless the input line was just "](". So this condition is not really doing anything.
To get the Test from the file, I used line.find() which gives the index of the character in the string.
print line.find("](")
print line.find(")")
print line[line.find("](")+2: line.find(")")]
output:
8
14
Test
So then you could just do this for getlink().
def getlink():
with open('findlink.txt') as infile, open('extractlink.txt', 'w') as outfile:
for line in infile:
outfile.write(line[line.find("](")+2: line.find(")")])
print("extractlink written.")
infile.close()
outfile.close()
extractlink.txt:
Test
This is just one simple solution. You could implement it differently, but you may want to use line.find() instead of line.strip().
I created a notepad text document called "connections.txt". I need to have some initial information inside it, several lines of just URLs. Each URL has it's own line. I put that in manually. Then in my program I have a function that checks if a URL is in the file:
def checkfile(string):
datafile = file(f)
for line in datafile:
if string in line:
return True
return False
where f is declared at the beginning of the program:
f = "D:\connections.txt"
Then I tried to write to the document like this:
file = open(f, "w")
if checkfile(user) == False:
usernames.append(user)
file.write("\n")
file.write(user)
file.close()
but it hasn't really been working correctly..I'm not sure what's wrong..am I doing it wrong?
I want the information in the notepad document to stay there ACROSS runs of the program. I want it to build up.
Thanks.
EDIT: I found something wrong... It needs to be file = f, not datafile = file(f)
But the problem is... It clears the text document every time I rerun the program.
f = "D:\connections.txt"
usernames = []
def checkfile(string):
file = f
for line in file:
if string in line:
return True
print "True"
return False
print "False"
file = open(f, "w")
user = "aasdf"
if checkfile(user) == False:
usernames.append(user)
file.write("\n")
file.write(user)
file.close()
I was working with the file command incorrectly...here is the code that works.
f = "D:\connections.txt"
usernames = []
def checkfile(string):
datafile = file(f)
for line in datafile:
if string in line:
print "True"
return True
print "False"
return False
user = "asdf"
if checkfile(user) == False:
usernames.append(user)
with open(f, "a") as myfile:
myfile.write("\n")
myfile.write(user)
The code that checks for a specific URL is ok!
If the problem is not erasing everything:
To write to the document without erasing everything you have to use the .seek() method:
file = open("D:\connections.txt", "w")
# The .seek() method sets the cursor to the wanted position
# seek(offset, [whence]) where:
# offset = 2 is relative to the end of file
# read more here: http://docs.python.org/2/library/stdtypes.html?highlight=seek#file.seek
file.seek(2)
file.write("*The URL you want to write*")
Implemented on your code will be something like:
def checkfile(URL):
# your own function as it is...
if checkfile(URL) == False:
file = open("D:\connections.txt", "w")
file.seek(2)
file.write(URL)
file.close()
How do I search and replace text in a file using Python 3?
Here is my code:
import os
import sys
import fileinput
print ("Text to search for:")
textToSearch = input( "> " )
print ("Text to replace it with:")
textToReplace = input( "> " )
print ("File to perform Search-Replace on:")
fileToSearch = input( "> " )
#fileToSearch = 'D:\dummy1.txt'
tempFile = open( fileToSearch, 'r+' )
for line in fileinput.input( fileToSearch ):
if textToSearch in line :
print('Match Found')
else:
print('Match Not Found!!')
tempFile.write( line.replace( textToSearch, textToReplace ) )
tempFile.close()
input( '\n\n Press Enter to exit...' )
Input file:
hi this is abcd hi this is abcd
This is dummy text file.
This is how search and replace works abcd
When I search and replace 'ram' by 'abcd' in above input file, it works as a charm. But when I do it vice-versa i.e. replacing 'abcd' by 'ram', some junk characters are left at the end.
Replacing 'abcd' by 'ram'
hi this is ram hi this is ram
This is dummy text file.
This is how search and replace works rambcd
As pointed out by michaelb958, you cannot replace in place with data of a different length because this will put the rest of the sections out of place. I disagree with the other posters suggesting you read from one file and write to another. Instead, I would read the file into memory, fix the data up, and then write it out to the same file in a separate step.
# Read in the file
with open('file.txt', 'r') as file :
filedata = file.read()
# Replace the target string
filedata = filedata.replace('abcd', 'ram')
# Write the file out again
with open('file.txt', 'w') as file:
file.write(filedata)
Unless you've got a massive file to work with which is too big to load into memory in one go, or you are concerned about potential data loss if the process is interrupted during the second step in which you write data to the file.
fileinput already supports inplace editing. It redirects stdout to the file in this case:
#!/usr/bin/env python3
import fileinput
with fileinput.FileInput(filename, inplace=True, backup='.bak') as file:
for line in file:
print(line.replace(text_to_search, replacement_text), end='')
As Jack Aidley had posted and J.F. Sebastian pointed out, this code will not work:
# Read in the file
filedata = None
with file = open('file.txt', 'r') :
filedata = file.read()
# Replace the target string
filedata.replace('ram', 'abcd')
# Write the file out again
with file = open('file.txt', 'w') :
file.write(filedata)`
But this code WILL work (I've tested it):
f = open(filein,'r')
filedata = f.read()
f.close()
newdata = filedata.replace("old data","new data")
f = open(fileout,'w')
f.write(newdata)
f.close()
Using this method, filein and fileout can be the same file, because Python 3.3 will overwrite the file upon opening for write.
You can do the replacement like this
f1 = open('file1.txt', 'r')
f2 = open('file2.txt', 'w')
for line in f1:
f2.write(line.replace('old_text', 'new_text'))
f1.close()
f2.close()
You can also use pathlib.
from pathlib2 import Path
path = Path(file_to_search)
text = path.read_text()
text = text.replace(text_to_search, replacement_text)
path.write_text(text)
(pip install python-util)
from pyutil import filereplace
filereplace("somefile.txt","abcd","ram")
Will replace all occurences of "abcd" with "ram".
The function also supports regex by specifying regex=True
from pyutil import filereplace
filereplace("somefile.txt","\\w+","ram",regex=True)
Disclaimer: I'm the author (https://github.com/MisterL2/python-util)
Open the file in read mode. Read the file in string format. Replace the text as intended. Close the file. Again open the file in write mode. Finally, write the replaced text to the same file.
try:
with open("file_name", "r+") as text_file:
texts = text_file.read()
texts = texts.replace("to_replace", "replace_string")
with open(file_name, "w") as text_file:
text_file.write(texts)
except FileNotFoundError as f:
print("Could not find the file you are trying to read.")
Late answer, but this is what I use to find and replace inside a text file:
with open("test.txt") as r:
text = r.read().replace("THIS", "THAT")
with open("test.txt", "w") as w:
w.write(text)
DEMO
With a single with block, you can search and replace your text:
with open('file.txt','r+') as f:
filedata = f.read()
filedata = filedata.replace('abc','xyz')
f.truncate(0)
f.write(filedata)
Your problem stems from reading from and writing to the same file. Rather than opening fileToSearch for writing, open an actual temporary file and then after you're done and have closed tempFile, use os.rename to move the new file over fileToSearch.
My variant, one word at a time on the entire file.
I read it into memory.
def replace_word(infile,old_word,new_word):
if not os.path.isfile(infile):
print ("Error on replace_word, not a regular file: "+infile)
sys.exit(1)
f1=open(infile,'r').read()
f2=open(infile,'w')
m=f1.replace(old_word,new_word)
f2.write(m)
Using re.subn it is possible to have more control on the substitution process, such as word splitted over two lines, case-(in)sensitive match. Further, it returns the amount of matches which can be used to avoid waste of resources if the string is not found.
import re
file = # path to file
# they can be also raw string and regex
textToSearch = r'Ha.*O' # here an example with a regex
textToReplace = 'hallo'
# read and replace
with open(file, 'r') as fd:
# sample case-insensitive find-and-replace
text, counter = re.subn(textToSearch, textToReplace, fd.read(), re.I)
# check if there is at least a match
if counter > 0:
# edit the file
with open(file, 'w') as fd:
fd.write(text)
# summary result
print(f'{counter} occurence of "{textToSearch}" were replaced with "{textToReplace}".')
Some regex:
add the re.I flag, short form of re.IGNORECASE, for a case-insensitive match
for multi-line replacement re.subn(r'\n*'.join(textToSearch), textToReplace, fd.read()), depending on the data also '\n{,1}'. Notice that for this case textToSearch must be a pure string, not a regex!
Besides the answers already mentioned, here is an explanation of why you have some random characters at the end:
You are opening the file in r+ mode, not w mode. The key difference is that w mode clears the contents of the file as soon as you open it, whereas r+ doesn't.
This means that if your file content is "123456789" and you write "www" to it, you get "www456789". It overwrites the characters with the new input, but leaves any remaining input untouched.
You can clear a section of the file contents by using truncate(<startPosition>), but you are probably best off saving the updated file content to a string first, then doing truncate(0) and writing it all at once.
Or you can use my library :D
I got the same issue. The problem is that when you load a .txt in a variable you use it like an array of string while it's an array of character.
swapString = []
with open(filepath) as f:
s = f.read()
for each in s:
swapString.append(str(each).replace('this','that'))
s = swapString
print(s)
I tried this and used readlines instead of read
with open('dummy.txt','r') as file:
list = file.readlines()
print(f'before removal {list}')
for i in list[:]:
list.remove(i)
print(f'After removal {list}')
with open('dummy.txt','w+') as f:
for i in list:
f.write(i)
you can use sed or awk or grep in python (with some restrictions). Here is a very simple example. It changes banana to bananatoothpaste in the file. You can edit and use it. ( I tested it worked...note: if you are testing under windows you should install "sed" command and set the path first)
import os
file="a.txt"
oldtext="Banana"
newtext=" BananaToothpaste"
os.system('sed -i "s/{}/{}/g" {}'.format(oldtext,newtext,file))
#print(f'sed -i "s/{oldtext}/{newtext}/g" {file}')
print('This command was applied: sed -i "s/{}/{}/g" {}'.format(oldtext,newtext,file))
if you want to see results on the file directly apply: "type" for windows/ "cat" for linux:
####FOR WINDOWS:
os.popen("type " + file).read()
####FOR LINUX:
os.popen("cat " + file).read()
I have done this:
#!/usr/bin/env python3
import fileinput
import os
Dir = input ("Source directory: ")
os.chdir(Dir)
Filelist = os.listdir()
print('File list: ',Filelist)
NomeFile = input ("Insert file name: ")
CarOr = input ("Text to search: ")
CarNew = input ("New text: ")
with fileinput.FileInput(NomeFile, inplace=True, backup='.bak') as file:
for line in file:
print(line.replace(CarOr, CarNew), end='')
file.close ()
I modified Jayram Singh's post slightly in order to replace every instance of a '!' character to a number which I wanted to increment with each instance. Thought it might be helpful to someone who wanted to modify a character that occurred more than once per line and wanted to iterate. Hope that helps someone. PS- I'm very new at coding so apologies if my post is inappropriate in any way, but this worked for me.
f1 = open('file1.txt', 'r')
f2 = open('file2.txt', 'w')
n = 1
# if word=='!'replace w/ [n] & increment n; else append same word to
# file2
for line in f1:
for word in line:
if word == '!':
f2.write(word.replace('!', f'[{n}]'))
n += 1
else:
f2.write(word)
f1.close()
f2.close()
def word_replace(filename,old,new):
c=0
with open(filename,'r+',encoding ='utf-8') as f:
a=f.read()
b=a.split()
for i in range(0,len(b)):
if b[i]==old:
c=c+1
old=old.center(len(old)+2)
new=new.center(len(new)+2)
d=a.replace(old,new,c)
f.truncate(0)
f.seek(0)
f.write(d)
print('All words have been replaced!!!')
I have worked this out as an exercise of a course: open file, find and replace string and write to a new file.
class Letter:
def __init__(self):
with open("./Input/Names/invited_names.txt", "r") as file:
# read the list of names
list_names = [line.rstrip() for line in file]
with open("./Input/Letters/starting_letter.docx", "r") as f:
# read letter
file_source = f.read()
for name in list_names:
with open(f"./Output/ReadyToSend/LetterTo{name}.docx", "w") as f:
# replace [name] with name of the list in the file
replace_string = file_source.replace('[name]', name)
# write to a new file
f.write(replace_string)
brief = Letter()
Like so:
def find_and_replace(file, word, replacement):
with open(file, 'r+') as f:
text = f.read()
f.write(text.replace(word, replacement))
def findReplace(find, replace):
import os
src = os.path.join(os.getcwd(), os.pardir)
for path, dirs, files in os.walk(os.path.abspath(src)):
for name in files:
if name.endswith('.py'):
filepath = os.path.join(path, name)
with open(filepath) as f:
s = f.read()
s = s.replace(find, replace)
with open(filepath, "w") as f:
f.write(s)
I've a file entitled 'users.txt' with the following structure; username:info_about_the_user.
Something like this:
users.txt:
mark:stuffabouthim anthony:stuffabouthim peter:stuffabouthim peterpeter:stuffabouthim peterpeterpeter:stuffabouthim peterpeterpeterpeter:stuffabouthim
The following part of the script needs to change a line (change info about an user) but I'm having problems when the string is duplicated (peter - peterpeter) and I dont know how to fix it.
def test():
fn = 'users.txt'
f = open(fn)
output = []
changeuser = 'peterpeter'
userinfo = 'HeIsTall'
for line in f:
if not changeuser+":" in line:
output.append(line)
f.close()
f = open(fn, 'w')
f.writelines(output)
f.close()
f = open("users.txt", "a")
f.write(changeuser + ":" + userinfo+"\n")
f = open("users.txt", "a")
test()
This is the input I have:
Input: users.txt:
mark:stuffabouthim anthony:stuffabouthim peter:stuffabouthim peterpeter:HesAwesome peterpeterpeter:stuffabouthim peterpeterpeterpeter:stuffabouthim
I want to change info about peterpeter and have the following output:
Output I want to have: users.txt:
mark:stuffabouthim anthony:stuff about him peter:stuffabouthim peterpeter:HeIsTall peterpeterpeter:stuffabouthim peterpeterpeterpeter:stuffabouthim
But this is the input I'm having. All the lines behind peterpeter are getting deleted among other things.
mark:stuffabouthim
anthony:stuffabouthim
peter:stuffabouthim
peterpeter:HeIsTall
Can anyone give me a help with the code below to have the desired output? Thanks.
You can have it the easy way with the fileinput module:
import fileinput
def test():
fn = 'users.txt'
changeuser = 'peterpeter'
newinfo = 'HeIsTall'
for line in fileinput.input(fn, inplace=1):
user, oldinfo = line.split(':')
print '%s:%s' % (user, newinfo if user == changeuser else oldinfo.replace('\n', ''))
if __name__ == "__main__":
test()
try this:
def test():
fn = 'users.txt.txt'
f = open(fn)
output = []
changeuser = 'peterpeter'
userinfo = 'HeIsTall'
for line in f:
if line.strip().split(':')[0]!=changeuser:
output.append(line)
else:
output.append(changeuser + ":" + userinfo+"\n")
f.close()
f = open(fn, 'w')
f.writelines(output)
f.close()
test()
output:
mark:stuffabouthim
anthony:stuffabouthim
peter:stuffabouthim
peterpeter:HeIsTall
peterpeterpeter:stuffabouthim
peterpeterpeterpeter:stuffabouthim
You got a logical error in the if-clause, which DELETES all peters*, the only peter remaining is the one you append to the file.
for line in f:
if not changeuser+":" in line: #THAT MEANS ALL PETERS ARE IGNORED!
output.append(line)
It's generaly easier to understand positive clauses then a negation:
for line in f:
if changeuser+":" in line:
output.append('%s:%s\n' %(changeuser,userinfo))
else:
output.append(line)
Good code is easy to read. Try to code like you would try to write a report! That leads automatically to spliting your code into smaller pieces like functions. e.g.:
lines = read_all_lines_from_file(filename)
change_user_info(lines, user, userinfo)
save_lines_to_file(lines, filename)
Your code gets split into smaller pieces and if an error occurs you can pin it down to a few lines of code instead of having to work over several pages. ;-)