65

I need to get the line number of a phrase in a text file. The phrase could be:

the dog barked

I need to open the file, search it for that phrase and print the line number.

I'm using Python 2.6 on Windows XP


This Is What I Have:

o = open("C:/file.txt")
j = o.read()
if "the dog barked" in j:
     print "Found It"
else:
     print "Couldn't Find It"

This is not homework, it is part of a project I am working on. I don't even have a clue how to get the line number.

Anthon
  • 69,918
  • 32
  • 186
  • 246
Zac Brown
  • 5,905
  • 19
  • 59
  • 107
  • what do you have so far? I mean, we know you know how to open a file. How are you searching for the phrase? – SilentGhost Oct 18 '10 at 16:43
  • 4
    @SilentGhost, I am a very strong Python programmer. Just never had to do this before. I have written several applications, specifically a web parental controls application that the company will release within the next few months. Just hit a "dead brain cell", thats all. – Zac Brown Oct 18 '10 at 16:59

11 Answers11

131
lookup = 'the dog barked'

with open(filename) as myFile:
    for num, line in enumerate(myFile, 1):
        if lookup in line:
            print 'found at line:', num
Sacha
  • 3,818
  • 2
  • 16
  • 10
  • 4
    Thank you for posting *the right way(tm)* to do it (well, except that line counting starts at 0 - ok for programmers but propably not for non-techies). +1 –  Oct 18 '10 at 16:54
  • This is what worked. Now, just a question... do you know how to read a specific line number in a text file? – Zac Brown Oct 18 '10 at 16:58
  • 3
    In python 2.6 and later, I think, `enumerate()` takes an argument of the number to start counting at, e.g. `enumerate(myFile, 1)`. – hughdbrown Oct 18 '10 at 17:09
  • Thanks for the comments, I edited it for python 2.6 (print) and the line starting at 1. – Sacha Oct 18 '10 at 17:15
  • 2
    You can check this post for the opening the file at a specific line: http://stackoverflow.com/questions/620367/python-how-to-jump-to-a-particular-line-in-a-huge-text-file – Sacha Oct 18 '10 at 17:18
13
f = open('some_file.txt','r')
line_num = 0
search_phrase = "the dog barked"
for line in f.readlines():
    line_num += 1
    if line.find(search_phrase) >= 0:
        print line_num

EDIT 1.5 years later (after seeing it get another upvote): I'm leaving this as is; but if I was writing today would write something closer to Ash/suzanshakya's solution:

def line_num_for_phrase_in_file(phrase='the dog barked', filename='file.txt')
    with open(filename,'r') as f:
        for (i, line) in enumerate(f):
            if phrase in line:
                return i
    return -1
  • Using with to open files is the pythonic idiom -- it ensures the file will be properly closed when the block using the file ends.
  • Iterating through a file using for line in f is much better than for line in f.readlines(). The former is pythonic (e.g., would work if f is any generic iterable; not necessarily a file object that implements readlines), and more efficient f.readlines() creates an list with the entire file in memory and then iterates through it. * if search_phrase in line is more pythonic than if line.find(search_phrase) >= 0, as it doesn't require line to implement find, reads more easily to see what's intended, and isn't easily screwed up (e.g., if line.find(search_phrase) and if line.find(search_phrase) > 0 both will not work for all cases as find returns the index of the first match or -1).
  • Its simpler/cleaner to wrap an iterated item in enumerate like for i, line in enumerate(f) than to initialize line_num = 0 before the loop and then manually increment in the loop. (Though arguably, this is more difficult to read for people unfamiliar with enumerate.)

See code like pythonista

dr jimbob
  • 17,259
  • 7
  • 59
  • 81
  • This is similar to Santiago's solution; except it should be >= 0, as if its at the beginning of the line, find will return 0 if the phrase is present. (If its not there it will be -1). – dr jimbob Oct 18 '10 at 16:48
  • -1 to get it back to 0. Using readlines is rarely a good idea, just iterate the file. –  Oct 18 '10 at 16:53
  • In the function line_num_for_phrase_in_file, is it IF PHRASE IN F, or IF PHRASE IN LINE? – BhishanPoudel Jun 22 '16 at 15:51
6
def get_line_number(phrase, file_name):
    with open(file_name) as f:
        for i, line in enumerate(f, 1):
            if phrase in line:
                return i

print get_line_number("the dog barked", "C:/file.txt")  # python2

#print(get_line_number("the dog barked", "C:/file.txt"))  # python3
suzanshakya
  • 3,524
  • 1
  • 26
  • 22
  • 1
    I would use `return None` rather than `return 0` but this is good. – Mark Ransom Oct 18 '10 at 17:03
  • I used `return 0` to make the return type of `get_line_number` integer. Why do you think `return None` is better ? – suzanshakya Oct 18 '10 at 17:16
  • 1
    `None` makes it clear that the phrase wasn't found, while `0` is just a convention. Also it ensures that if the result isn't checked by the caller, the program will likely fail in a spectacular way when the bug is tripped, making debugging easier. – Mark Ransom Oct 18 '10 at 17:31
  • Thanks Mark for the explanation. – suzanshakya Oct 18 '10 at 18:23
3

suzanshakya, I'm actually modifying your code, I think this will simplify the code, but make sure before running the code the file must be in the same directory of the console otherwise you'll get error.

lookup="The_String_You're_Searching"
file_name = open("file.txt")
for num, line in enumerate(file_name,1):
        if lookup in line:
            print(num)
Eric Aya
  • 69,473
  • 35
  • 181
  • 253
1
listStr = open("file_name","mode")

if "search element" in listStr:
    print listStr.index("search element")  # This will gives you the line number
Community
  • 1
  • 1
1

Open your file, and then do something like...

for line in f:
    nlines += 1
    if (line.find(phrase) >= 0):
        print "Its here.", nlines

There are numerous ways of reading lines from files in Python, but the for line in f technique is more efficient than most.

salezica
  • 74,081
  • 25
  • 105
  • 166
  • 1
    Wrong? Where? ...? If it's the > instead of >=, I just fixed it, you are right, and ... you could've just pointed that out instead of saying the answer was wrong and embarrasing. – salezica Oct 18 '10 at 16:54
  • @santi: embarrassment was writing c code in python. See Sacha's answer – SilentGhost Oct 18 '10 at 16:55
  • Yeah, I was unable to get it working. Thanks for posting though. – Zac Brown Oct 18 '10 at 16:57
  • @silent come oooon, the question wasn't "what's the most pythonesque way of finding a string in file", maan. Zachary seemed to know little about python, so I wrote a more language-agnostic answer. He is right, tough, Zach: for a better-looking solution, see Sacha's. – salezica Oct 18 '10 at 17:01
  • @mark: of course it's not wrong! *any more*. Santiago seems to have a thing for parentheses. – SilentGhost Oct 18 '10 at 17:04
  • @Santiago: on opposite! OP says he's a *very strong Python programmer* – SilentGhost Oct 18 '10 at 17:05
  • They can hear you guys, they are a few lines above these comments. Leave my parentheses alone. They have feelings, you know. – salezica Oct 18 '10 at 17:05
  • What was Sacha's answer? It seems to have been removed. – dotancohen Jul 18 '13 at 19:37
1

You can use list comprehension:

content = open("path/to/file.txt").readlines()

lookup = 'the dog barked'

lines = [line_num for line_num, line_content in enumerate(content) if lookup in line_content]

print(lines)
Alon Barad
  • 1,491
  • 1
  • 13
  • 26
0

Here's what I've found to work:

f_rd = open(path, 'r')
file_lines = f_rd.readlines()
f_rd.close()

matches = [line for line in file_lines if "chars of Interest" in line]
index = file_lines.index(matches[0])
Onkar Raut
  • 31
  • 1
0
for n,line in enumerate(open("file")):
    if "pattern" in line: print n+1
ghostdog74
  • 327,991
  • 56
  • 259
  • 343
0

It's been a solid while since this was posted, but here's a nifty one-liner. Probably not worth the headache, but just for fun :)

from functools import reduce 
from pathlib import Path

my_lines       = Path('path_to_file').read_text().splitlines()       
found, linenum = reduce(lambda a, b: a if a[0] else (True, a[1]) if testid in b else (False, a[1]+1), [(False,0)] + my_lines)
            
print(my_lines[linenum]) if found else print(f"Couldn't find {my_str}")

Note that if there are two instances in the file, it wil

optimus_prime
  • 1,039
  • 2
  • 10
  • 21
0

An one-liner solution:

l_num = open(file).read()[:open(file).read().index(phrase)].count('\n') + 1

and an IO safer version:

l_num = (h.close() or ((f := open(file, 'r', encoding='utf-8')).read()[:(f.close() or (g := open(file, 'r', encoding='utf-8')).read().index(g.close() or phrase))].count('\n'))) if phrase in (h := open(file, 'r', encoding='utf-8')).read() else None

Explain:

file = 'file.txt'
phrase = 'search phrase'
with open(file, 'r', encoding='utf-8') as f:
    text = f.read()
    if phrase in text:
        phrase_index = text.index(phrase)
        l_num = text[:phrase_index].count('\n') + 1  # Nth line has n-1 '\n's before
    else:
        l_num = None
KumaTea
  • 504
  • 5
  • 17