Reputation: 525
here is an example text file
the bird flew
the dog barked
the cat meowed
here is my code to find the line number of the phrase i want to delete
phrase = 'the dog barked'
with open(filename) as myFile:
for num, line in enumerate(myFile, 1):
if phrase in line:
print 'found at line:', num
what can i add to this to be able to delete the line number (num) i have tried
lines = myFile.readlines()
del line[num]
but this doesnt work how should i approach this?
Upvotes: 5
Views: 39287
Reputation: 411
Implementing @atomh33ls numpy approach
So you want to delete any line in the file that contain the phrase
string, right? instead of just deleting the phrase
string
import numpy as np
phrase = 'the dog barked'
nums = []
with open("yourfile.txt") as myFile:
for num1, line in enumerate(myFile, 0):
# Changing from enumerate(myFile, 1) to enumerate(myFile, 0)
if phrase in line:
nums.append(num1)
a=np.genfromtxt("yourfile.txt",dtype=None, delimiter="\n", encoding=None )
with open('yourfile.txt','w') as f:
for el in np.delete(a,nums,axis=0):
f.write(str(el)+'\n')
where text file is,
the bird flew
the dog barked
the cat meowed
produces
the bird flew
the cat meowed
Upvotes: 0
Reputation: 31
I found another solution that works efficiently and gets by without doing all the icky and not so elegant counting of lines within the file object:
del_line = 3 #line to be deleted: no. 3 (first line is no. 1)
with open("textfile.txt","r") as textobj:
list = list(textobj) #puts all lines in a list
del list[del_line - 1] #delete regarding element
#rewrite the textfile from list contents/elements:
with open("textfile.txt","w") as textobj:
for n in list:
textobj.write(n)
Detailed explanation for those who want it:
(1) Create a variable containing an integer value of the line-number you want to have deleted. Let's say I want to delete line #3:
del_line = 3
(2) Open the text file and put it into a file-object. Only reading-mode is necessary for now. Then, put its contents into a list:
with open("textfile.txt","r") as textobj:
list = list(textobj)
(3) Now every line should be an indexed element in "list". You can proceed by deleting the element representing the line you want to have deleted:
del list[del_line - 1]
At this point, if you got the line no. that is supposed to be deleted from user-input, make sure to convert it to integer first since it will be in string format most likely(if you used "input()").
It's del_line - 1 because the list's element-index starts at 0. However, I assume you (or the user) start counting at "1" for line no. 1, in which case you need to deduct 1 to catch the correct element in the list.
(4) Open the list file again, this time in "write-mode", rewriting the complete file. After that, iterate over the updated list, rewriting every element of "list" into the file. You don't need to worry about new lines because at the moment you put the contents of the original file into a list (step 2), the \n escapes will also be copied into the list elements:
with open("textfile.txt","w") as textobj:
for n in list:
textobj.write(n)
This has done the job for me when I wanted the user to decide which line to delete in a certain text file. I think Martijn Pieters's answer does sth. similar, however his explanation is to little for me to be able to tell.
Upvotes: 3
Reputation: 31050
Assuming num
is the line number to remove:
import numpy as np
a=np.genfromtxt("yourfile.txt",dtype=None, delimiter="\n")
with open('yourfile.txt','w') as f:
for el in np.delete(a,(num-1),axis=0):
f.write(str(el)+'\n')
Upvotes: 2
Reputation: 249
Try
lines = myFile.readlines()
mylines = [x for x in lines if x.find(phrase) < 0]
Upvotes: 0
Reputation: 620
A user by the name of gnibbler posted something similar to this on another thread.
Modify the file in place, offending line is replaced with spaces so the remainder of the file does not need to be shuffled around on disk. You can also "fix" the line in place if the fix is not longer than the line you are replacing
If the other program can be changed to output the fileoffset instead of the line number, you can assign the offset to p directly and do without the for loop
import os
from mmap import mmap
phrase = 'the dog barked'
filename = r'C:\Path\text.txt'
def removeLine(filename, num):
f=os.open(filename, os.O_RDWR)
m=mmap(f,0)
p=0
for i in range(num-1):
p=m.find('\n',p)+1
q=m.find('\n',p)
m[p:q] = ' '*(q-p)
os.close(f)
with open(filename) as myFile:
for num, line in enumerate(myFile, 1):
if phrase in line:
removeLine(filename, num)
print 'Removed at line:', num
Upvotes: 3
Reputation: 142166
You could use the fileinput
module to update the file - note this will remove all lines containing the phrase:
import fileinput
for line in fileinput.input(filename, inplace=True):
if phrase in line:
continue
print(line, end='')
Upvotes: 8
Reputation: 1122252
You start counting at one, but python indices are always zero-based.
Start your line count at zero:
for num, line in enumerate(myFile): # default is to start at 0
or subtract one from num
, deleting from lines
(not line
):
del lines[num - 1]
Note that in order for your .readlines()
call to return any lines, you need to either re-open the file first, or seek to the start:
myFile.seek(0)
Upvotes: 0