How do you skip to the next lines of a file being looped line by line. This code below is skipping lines for the total count in the 2nd loop, I want it to skip the line 1 by 1 for the desired count so I can pull the right information from the file.
f = open("someTXT", "r")
lines = iter(f.readlines())
for line in lines:
thisLine = line.split(',')
if len(thisLine) > 3:
count = thisLine[4]
for i in range(1,int(count)):
next(lines)
print(line)
Here's a bit of code review. Not sure what you're asking though.
Use the context manager to open files:
with open("someTXT", 'rU') as f: # Universal newline flag, best practice
# lines = iter(f) # no need for this, my_file is an iterator
container = [] # use a container to hold your lines
for line in f:
test = test_for_correct_lines(line) # return True if keep and print
if test:
container.append(line)
# join the lines you want to keep with a newline and print them
print('\n'.join(container))
Related
I have a .txt file that I created with multiple lines.
When I run a for loop, with a count accumulator, it skips lines.
It skips the top line, and starts with the second, prints the fourth, the sixth, etc.
What is it I'm missing?
def main():
# Open file line_numbers.txt
data_file = open('line_numbers.txt', 'r')
# initialize accumulatior
count = 1
# Read all lines in data_file
for line in data_file:
# Get the data from the file
line = data_file.readline()
# Display data retrieved
print(count, ": ", line)
# add to count sequence
count += 1
Try removing the "line=data_file.readline()" altogether? I suspect the "for line in data_file:" is also a readline operation.
You for loop is iterating over the data_file and your readline() is competing with it. Erase the line = data_file.readline() line of your code for this result:
# Read all lines in data_file
count = 1
for line in data_file:
# Display data retrieved
print(count, ": ", line)
# add to count sequence
count += 1
for line in data_file already gets the text of each line for you - the subsequent call to readline then gets the following line. In other words, removing the call to readline will do what you want. At the same time, you don't need to keep track of an accumulator variable yourself - python has a built-in way of doing this using enumerate - in other words:
data_file = open('line_numbers.txt', 'r')
for count, line in enumerate(data_file):
...
I have a similar question to delete multiple line
I want to delete the line and the next 4 lines. This is my code:
bind = open('/etc/bind/named.conf.local','r')
a = dict['name']
for line in bind:
if a in line:
print('line exist')
''' and delete this line and 4 line after it'''
else:
print('line does not exist')
I want to save modify text in /etc/bind/named.conf.local in place, without fileinput. I do not want skip 4 line I want to delete them from the file. I do not want to read it and write it again and skip 4 lines.
What should I do?
I think the following code does what you're looking for. You will have to adjust settings filename, keyword and delete to your needs. The code will delete delete lines from file filename every time keyword is found in a line. (Including the keyword line.)
# Settings
filename = "test.txt"
keyword = "def"
delete = 2
# Read lines from file
with open(filename) as f:
lines = f.readlines()
# Process lines
for i, line in enumerate(lines):
if keyword in line:
del lines[i:i + delete]
# Save modified lines to file
with open(filename, "w") as f:
f.writelines(lines)
Example test.txt before:
abc
def
ghi
jkl
Example test.txt afterwards:
abc
jkl
If you don't want to use fileinput, you can also read all the lines of your file, write them (except for the lines you skip using next(f)) to a tempfile.NamedTemporaryFile and replace the original file with the temporary file.
from pathlib import Path
from tempfile import NamedTemporaryFile
named_conf = Path('/etc/bind/named.conf.local')
with open(named_conf) as infile:
with NamedTemporaryFile("w", delete=False) as outfile:
for line in infile:
if line_should_be_deleted(line):
# skip this line and the 4 lines after it
for _ in range(4):
next(infile)
else:
outfile.write(line)
Path(outfile.name).replace(named_conf)
But you should just use fileinput, like the answer to the question you linked to says, since it does the tempfile stuff for you.
It all boils down to keeping a skip count that you initialize with the first occurrence of the matching line and increase afterward:
match = "text line to match"
with open('input.txt','r') as lines:
with open('output.txt','w') as output:
skip = -1
for line in lines:
skip += skip >= 0 or skip < 0 and line.strip("\n") == match
if skip not in range(5):
output.write(line)
If what you're trying to avoid is reading lines one by one, you could write it like this (but you still need to open the files)
match = "text line to match"
lines = open('input.txt','r').read().split("\n")
matchPos = lines.index(match)
del lines[matchPos:matchPos+5]
open('output.txt','w').write("\n".join(lines))
bind = open('text.txt','r')
a = dict['name']
lines = bind.readlines()
i = 0
while i < len(lines):
if a in lines[i]:
del lines[i:i+5]
i += 1
print(lines)
bind = open('/etc/bind/named.conf.local','r')
textfile = bind.readlines()
a = 'some text'
for line_num in range(len(textfile)):
try:
if a in textfile[line_num]:
print('line exists')
del textfile[line_num:line_num+5]
except IndexError:
break
writer = open("/etc/bind/named.conf.local","w")
writer.write(''.join(textfile))
writer.close()
I currently have some code that grabs all the lines after the first one in a file and saves it to the variable resourceslist . I want to add some code that says if there's only one line in the file then give variable resourceslist the value "oneline"
with open('filepaths', "r+") as f:
if index + 1 > len(f):
for _ in range(1):
next(f)
for lines in f:
resourceslist = f.read()
else:
resourceslist = "oneline"
You can write the following; your first for loop isn't necessary, as it will never actually loop, and the second one is unnecessary because you want to read the entire (remaining) contents of the file into resourceslist, without otherwise iterating over the remaining lines.
with open('filepath') as f:
next(f) # Skip the first line
resourceslist = f.read()
if not resourceslist: # i.e., f.read() returned the empty string
resourceslist = "oneline"
I want to find the lines which start with a word of a list. If the word is found i want the line it stands in and the previous line to be deleted.
I am able to get the line and the previos one and print them but i can not get my head around not to pass them to my outputfile.
F.e.:
in-put:
This is not supposed to be deleted.
This shall be deleted.
Titel
This is not supposed to be deleted.
This is not supposed to be deleted
out-put:
This is not supposed to be deleted.
This is not supposed to be deleted.
This is not supposed to be deleted
I tried it with this code, but i keep getting a TypeError: 'str' object does not support item assignment
with open(file1) as f_in, open(file2, 'w') as f_out:
lines = f_in.read().splitlines()
for i, line in enumerate(lines):
clean = True
if line.startswith(('Text', 'Titel')):
for (line[i-1]) in lines:
clean = False
for line in lines:
clean =False
if clean == True:
f_out.write(line)
You don't have to read the file at once. Read the lines after each other, and store the current line, but write it out only after the next read, or not.
with open("file1") as finp, open("file2","w") as fout:
lprev=""
for line in finp:
if line.startswith("Titel") or line.startswith("Text"):
lprev=""
continue
if lprev:
fout.write(lprev)
lprev=line
if lprev:
fout.write(lprev) # write out the last line if needed
First keep track of which lines you want to copy:
lines_to_keep = []
with open(file1) as f_in:
deleted_previous_line = True
for line in f_in:
if line.startswith(('Text', 'Titel')):
if not deleted_previous_line:
del lines_to_keep[-1]
deleted_previous_line = True
continue
deleted_previous_line = False
lines_to_keep.append(line)
The trick with the deleted_previous_line is necessary to ensure it does not delete too many lines if consecutive lines start with 'Text' or 'Titel'.
Then write it to your output file
with open(file2, 'w') as f_out:
f_out.writelines(lines_to_keep)
I have a file, like this:
<prop type="ltattr-match">1-1</prop>
id =>3</prop>
<tuv xml:lang="en">
<seg> He is not a good man </seg>
And what I want is to detect the third line before the line He is not a good man , i.e (id =>3). The file is big. what I can do
I suggest using a double ended queue with a maximum length: this way, only the required amount of "backlog" is stored and you don't have to fiddle around with slices manually. We don't need the "double-ended-ness", but the normal Queue class blocks if the queue is full.
import collections
dq = collections.deque([], 3) # create an empty queue
with open("mybigfile.txt") as file:
for line in file.readlines():
if line.startswith('<seg>'):
return dq[0] # or add to list
dq.append(line) # save the line, if already 3 lines stored,
# discard oldest line.
with open("mybigfile.txt") as file:
lines = file.readlines()
for idx, line in enumerate(lines):
if line.startswith("<seg>"):
line_to_detect = lines[idx-3]
#use idx-2 if you want the _second_ line before this one,
#ex `id =>3</prop>`
print "This line was detected:"
print line_to_detect
Result:
This line was detected:
<prop type="ltattr-match">1-1</prop>
As we previously discussed in chat, this method can be memory intensive for very large files. But 100 pages isn't very large, so this should be fine.
Read each line in sequence, remembering only the last 3 read at any point.
Something like:
# Assume f is a file object open to your file
last3 = []
last3.append( f.readline() )
last3.append( f.readline() )
last3.append( f.readline() )
while ( True ):
line = f.readline()
if (line satisfies condition):
break
last3 = last3[1:]+[line]
# At this point last3[0] is 3 lines before the matching line
You'll need to modify this to handle files w/ < 3 lines, or if no line matches your condition.
file = "path/to/the/file"
f = open(file, "r")
lines = f.readlines()
f.close()
i = 0
for line in lines:
if "<seg> He is not a good man </seg>" in line:
print(lines[i]) #Print the prvious line
else
i += 1
If you need the second line before just change to print(lines[i-1])