Python: Print next x lines from text file when hitting string - python

The situation is as follows:
I have a .txt file with results of several nslookups.
I want to loop tru the file and everytime it hits the string "Non-authoritative answer:" the scripts has to print the following 8 lines from that position. If it works I shoud get all the positive results in my screen :).
First I had the following code:
#!/bin/usr/python
file = open('/tmp/results_nslookup.txt', 'r')
f = file.readlines()
for positives in f:
if 'Authoritative answers can be found from:' in positives:
print positives
file.close()
But that only printed "Authoritative answers can be found from:" the times it was in the .txt.
The code what I have now:
#!/bin/usr/python
file = open('/tmp/results_nslookup.txt', 'r')
lines = file.readlines()
i = lines.index('Non-authoritative answer:\n')
for line in lines[i-0:i+9]:
print line,
file.close()
But when I run it, it prints the first result nicely to my screen but does not print the other positve results.
p.s. I am aware of socket.gethostbyname("foobar.baz") but first I want to solve this basic problem.
Thank you in advance!

You can use the file as an iterator, then print the next 8 lines every time you find your sentence:
with open('/tmp/results_nslookup.txt', 'r') as f:
for line in f:
if line == 'Non-authoritative answer:\n':
for i in range(8):
print(next(lines).strip())
Each time you use the next() function on the file object (or loop over it in a for loop), it'll return the next line in that file, until you've read the last line.
Instead of the range(8) for loop, I'd actually use itertools.islice:
from itertools import islice
with open('/tmp/results_nslookup.txt', 'r') as f:
for line in f:
if line == 'Non-authoritative answer:\n':
print(''.join(islice(f, 8)))

file = open('/tmp/results_nslookup.txt', 'r')
for line in file:
if line=='Non-authoritative answer:\n':
for _ in range(8):
print file.next()
By the way: don't ever use the name file for a variable because it is the name of a built-in function.

Related

How can I print the lines from the text file next to random generated numbers

The text file is "ics2o.txt" and I don't know how to print numbers next to the lines
import random
print ("----------------------------------------------------------")
print ("Student Name Student Mark")
print ("----------------------------------------------------------")
f = open("ics2o.txt")
for line in f:
x = len(f.readlines())
for i in range (x):
contents = f.read()
print(str(contents) + str(random.randint(75,100)))
for line in f:
x = len(f.readlines())
for i in range (x):
contents = f.read()
print(str(contents) + str(random.randint(75,100)))
The problem is that you are reading the file in at least 3 different ways which causes none of them to work the way you want. In particular, f.readlines() consumes the entire file buffer, so when you next do f.read() there is nothing left to read. Don't mix and match these. Instead, you should use line since you are iterating over the file already:
for line in f:
print(line + str(random.randint(75,100)))
The lesson here is don't make things any more complicated than they need to be.
Firstly, doing print("----...") is a bad practice, at least use string multiplication:print("-"*10)
Secondly, always open files using 'with' keyword. (u can google it up why)
Thirdly, the code:
with open("ics2o.txt") as f:
for i,j in enumerate(f):
print(i,j)

Read in every line that starts with a certain character from a file

I am trying to read in every line in a file that starts with an 'X:'. I don't want to read the 'X:' itself just the rest of the line that follows.
with open("hnr1.abc","r") as file: f = file.read()
id = []
for line in f:
if line.startswith("X:"):
id.append(f.line[2:])
print(id)
It doesn't have any errors but it doesn't print anything out.
try this:
with open("hnr1.abc","r") as fi:
id = []
for ln in fi:
if ln.startswith("X:"):
id.append(ln[2:])
print(id)
dont use names like file or line
note the append just uses the item name not as part of the file
by pre-reading the file into memory the for loop was accessing the data by character not by line
for line in f:
search = line.split
if search[0] = "X":
storagearray.extend(search)
That should give you an array of all the lines you want, but they'll be split into separate words. Also, you'll need to have defined storagearray before we call it in the above block of code. It's an inelegant solution, as I'm a learner myself, but it should do the job!
edit: If you want to output the lines, simply use python's inbuilt print function:
str(storagearray)
print storagearray
Read every line in the file (for loop)
Select lines that contains X:
Slice the line with index 0: with starting char's/string as X: = ln[0:]
Print lines that begins with X:
for ln in input_file:
if ln.startswith('X:'):
X_ln = ln[0:]
print (X_ln)

How to read first line of a file twice?

I have a big files with many lines and want to read the first line first and then loop through all lines starting with the first line again.
I first thought that something like that would do it:
file = open("fileName", 'r')
first_line = file.readline()
DoStuff_1(first_line)
for line in file:
DoStuff_2(line)
file.close()
But this issue with this script is that the first line that is passed to DoStuff_2 is the second line and not the first one. I don't have a good intuition of what kind of object file is. I think it is an iterator and don't really know how to deal with it. The bad solution I found is
file = open("fileName", 'r')
first_line = file.readline()
count = 0
for line in file:
if count == 0:
count = 1
DoStuff_1(first_line)
DoStuff_2(line)
file.close()
But it is pretty dumb and is computationally a bit costly as it runs a if statement at each iteration.
You could do this:
with open('fileName', 'r') as file:
first_line = file.readline()
DoStuff_1(first_line)
DoStuff_2(first_line)
# remaining lines
for line in file:
DoStuff_2(line)
Note that I changed your code to use with so file is automatically closed.
I'd like using a generator to abstract your general control flow. Something like:
def first_and_file(file_obj):
"""
:type file_obj: file
:rtype: (str, __generator[str])
"""
first_line = next(file_obj)
def gen_rest():
yield first_line
yield from file_obj
return first_line, gen_rest()
In Python 2.7, swap out the yield from for:
for line in file_obj:
yield line
Another answer is to just open the file twice.
with open("file.txt", "r") as r:
Do_Stuff1(r.readline())
with open("file.txt", "r") as r:
for line in r:
Do_Stuff2(line)
One of the solutions for a general case of this question is to save the line number on which you are. After completing an operation which requires you to go a previous line relative to the current line, use the line number variable by doing file.seek(0) and then looping over file.readline() the required number of times.

How to Iterate over readlines() in python

I am trying to add lines from a txt file to a python list for iteration, and the script wants to print every line and return an error. I'm using the readlines() function, but when I use list.remove(lines), it returns an error: File "quotes.py", line 20, in main list.remove(lines) TypeError: remove() takes exactly one argument (0 given).
def main():
while True:
try:
text_file = open("childrens-catechism.txt", "r")
lines = text_file.readlines()
# print lines
# print len(lines)
if len(lines) > 0:
print lines
list.remove(lines)
time.sleep(60)
else:
print "No more lines!"
break
text_file.close()
I can't see what I'm doing wrong. I know it has to do with list.remove(). Thank you in advance.
You can write in this way. It will save you some time and give you more efficiency.
import time
def main():
with open("childrens-catechism.txt", "r") as file:
for line in file:
print line,
time.sleep(60)
Try this as per your requirements, this will do what you need.
import time
def main():
with open("childrens-catechism.txt", "r") as file:
for lines in file.readlines():
if len(lines) > 0:
for line in lines:
print line
lines.remove(line)
else:
print "No more lines to remove"
time.sleep(60)
lines is a list here from your txt. files, and list.remove(lines) is not a correct syntax, you trying to delete a list on list. list is a function in Python. You can delete the elements in lines like;
del lines[0]
del lines[1]
...
or
lines.remove("something")
The logic is, remove() is deleting an element in a list, you have to write that list before remove() after then you have to write the thing that you want to delete in paranthesis of remove() function.
On opening a file, we can convert the file lines onto a list,
lines = list(open("childrens-catechism.txt", "r"))
From this list we can now remove entries with length greater than zero, like this,
for line in lines:
if len(line) > 0:
# do sth
lines.remove(line)
If you are trying to read all the lines from the file and then print them in order, and then delete them after printing them I would recommend this approach:
import time
try:
file = open("childrens-catechism.txt")
lines = file.readlines()
while len(lines) != 0:
print lines[0],
lines.remove(lines[0])
time.sleep(60)
except IOError:
print 'No such file in directory'
This prints the first line and then deletes it. When the first value is removed, the list shifts one up making the previous line (lines[1]) the new start to the list namely lines[0].
EDITED:
If you wanted to delete the line from the file as well as from the list of lines you will have to do this:
import time
try:
file = open("childrens-catechism.txt", 'r+') #open the file for reading and writing
lines = file.readlines()
while len(lines) != 0:
print lines[0],
lines.remove(lines[0])
time.sleep(60)
file.truncate(0) #this truncates the file to 0 bytes
except IOError:
print 'No such file in directory'
As far as deleting the lines from the file line for line I am not too sure if that is possible or efficient.

How to only read lines in a text file after a certain string?

I'd like to read to a dictionary all of the lines in a text file that come after a particular string. I'd like to do this over thousands of text files.
I'm able to identify and print out the particular string ('Abstract') using the following code (gotten from this answer):
for files in filepath:
with open(files, 'r') as f:
for line in f:
if 'Abstract' in line:
print line;
But how do I tell Python to start reading the lines that only come after the string?
Just start another loop when you reach the line you want to start from:
for files in filepath:
with open(files, 'r') as f:
for line in f:
if 'Abstract' in line:
for line in f: # now you are at the lines you want
# do work
A file object is its own iterator, so when we reach the line with 'Abstract' in it we continue our iteration from that line until we have consumed the iterator.
A simple example:
gen = (n for n in xrange(8))
for x in gen:
if x == 3:
print('Starting second loop')
for x in gen:
print('In second loop', x)
else:
print('In first loop', x)
Produces:
In first loop 0
In first loop 1
In first loop 2
Starting second loop
In second loop 4
In second loop 5
In second loop 6
In second loop 7
You can also use itertools.dropwhile to consume the lines up to the point you want:
from itertools import dropwhile
for files in filepath:
with open(files, 'r') as f:
dropped = dropwhile(lambda _line: 'Abstract' not in _line, f)
next(dropped, '')
for line in dropped:
print(line)
Use a boolean to ignore lines up to that point:
found_abstract = False
for files in filepath:
with open(files, 'r') as f:
for line in f:
if 'Abstract' in line:
found_abstract = True
if found_abstract:
#do whatever you want
You can use itertools.dropwhile and itertools.islice here, a pseudo-example:
from itertools import dropwhile, islice
for fname in filepaths:
with open(fname) as fin:
start_at = dropwhile(lambda L: 'Abstract' not in L.split(), fin)
for line in islice(start_at, 1, None): # ignore the line still with Abstract in
print line
To me, the following code is easier to understand.
with open(file_name, 'r') as f:
while not 'Abstract' in next(f):
pass
for line in f:
#line will be now the next line after the one that contains 'Abstract'
Just to clarify, your code already "reads" all the lines. To start "paying attention" to lines after a certain point, you can just set a boolean flag to indicate whether or not lines should be ignored, and check it at each line.
pay_attention = False
for line in f:
if pay_attention:
print line
else: # We haven't found our trigger yet; see if it's in this line
if 'Abstract' in line:
pay_attention = True
If you don't mind a little more rearranging of your code, you can also use two partial loops instead: one loop that terminates once you've found your trigger phrase ('Abstract'), and one that reads all following lines. This approach is a little cleaner (and a very tiny bit faster).
for skippable_line in f: # First skim over all lines until we find 'Abstract'.
if 'Abstract' in skippable_line:
break
for line in f: # The file's iterator starts up again right where we left it.
print line
The reason this works is that the file object returned by open behaves like a generator, rather than, say, a list: it only produces values as they are requested. So when the first loop stops, the file is left with its internal position set at the beginning of the first "unread" line. This means that when you enter the second loop, the first line you see is the first line after the one that triggered the break.
Making a guess as to how the dictionary is involved, I'd write it this way:
lines = dict()
for filename in filepath:
with open(filename, 'r') as f:
for line in f:
if 'Abstract' in line:
break
lines[filename] = tuple(f)
So for each file, your dictionary contains a tuple of lines.
This works because the loop reads up to and including the line you identify, leaving the remaining lines in the file ready to be read from f.

Categories

Resources