Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Print 4 lines before and after a "match" found 1

Status
Not open for further replies.

Tester_V

Technical User
Nov 22, 2019
54
US
Greeting!
I’m trying to print 4 lines before and after a “match” found in a line.
I do not understand how to do it with my current knowledge of Python Confused but I found 2 snippets,
One finds lines Before the match and one After the match. Need help putting them together.
Thank you.

Python:
from itertools import islice
 
with open(myfile, "r") as f:
    lines = f.readlines() 
    for index, line in enumerate(lines):  
        if "FIND" in line:  
#            print(line.rstrip())  
            print("".join(lines[max(0,index-4):index]))  # print 4 lines preceeding it
 
with open(myfile, "r") as f:
    for line in f:
        #print (line)
        if "FIND" in line:
            #print (line)
            #print("".join(line))
            print ("".join(islice(f,4)))   ### 4 Lines after match  ###
 
Hi

The first half of your code is using [tt]file.readlines()[/tt] to slurp the entire file into memory. That allows you to easily access any line, so just change the slice's 2[sup]nd[/sup] value :
Python:
with [COLOR=orange]open[/color][teal]([/teal]myfile[teal],[/teal] [i][green]"r"[/green][/i][teal])[/teal] as f[teal]:[/teal]
    lines [teal]=[/teal] f[teal].[/teal][COLOR=orange]readlines[/color][teal]()[/teal]
    [b]for[/b] index[teal],[/teal] line [b]in[/b] [COLOR=orange]enumerate[/color][teal]([/teal]lines[teal]):[/teal]
        [b]if[/b] [i][green]"FIND"[/green][/i] [b]in[/b] line[teal]:[/teal]
            [b]print[/b][teal]([/teal][i][green]""[/green][/i][teal].[/teal][COLOR=orange]join[/color][teal]([/teal]lines[teal][[/teal][COLOR=orange]max[/color][teal]([/teal][purple]0[/purple][teal],[/teal] index [teal]-[/teal] [purple]4[/purple][teal]):[/teal]index [teal]+[/teal] [purple]5[/purple][teal]]))[/teal]

While that is simple and readable, work probably not work fine on bigger files. For those the second half of your code is more suitable, but unfortunately [tt]islice()[/tt] can not handle negative indexes, so you have to handle the before lines yourself :
Python:
[red]from[/red] itertools [red]import[/red] islice

before [teal]= [][/teal]
with [COLOR=orange]open[/color][teal]([/teal]myfile[teal],[/teal] [i][green]"r"[/green][/i][teal])[/teal] as f[teal]:[/teal]
    [b]for[/b] line [b]in[/b] f[teal]:[/teal]
        before[teal].[/teal][COLOR=orange]append[/color][teal]([/teal]line[teal])[/teal]
        [b]if[/b] [COLOR=orange]len[/color][teal]([/teal]before[teal]) >[/teal] [purple]5[/purple][teal]:[/teal]
            before[teal].[/teal][COLOR=orange]pop[/color][teal]([/teal][purple]0[/purple][teal])[/teal]
        [b]if[/b] [i][green]"FIND"[/green][/i] [b]in[/b] line[teal]:[/teal]
            [b]print[/b][teal]([/teal][i][green]""[/green][/i][teal].[/teal][COLOR=orange]join[/color][teal]([/teal]before[teal]) +[/teal] [i][green]""[/green][/i][teal].[/teal][COLOR=orange]join[/color][teal]([/teal][COLOR=orange]islice[/color][teal]([/teal]f[teal],[/teal] [purple]4[/purple][teal])))[/teal]

The above is the simplified version, but all those [tt]list.pop()[/tt] will slow it down, so you better avoid it :
Python:
[red]from[/red] itertools [red]import[/red] islice

before [teal]= [][/teal]
before_index [teal]=[/teal] [purple]0[/purple]
with [COLOR=orange]open[/color][teal]([/teal]myfile[teal],[/teal] [i][green]"r"[/green][/i][teal])[/teal] as f[teal]:[/teal]
    [b]for[/b] line [b]in[/b] f[teal]:[/teal]
        [b]if[/b] [teal]([/teal][COLOR=orange]len[/color][teal]([/teal]before[teal]) <[/teal] [purple]5[/purple][teal]):[/teal]
            before[teal].[/teal][COLOR=orange]append[/color][teal]([/teal]line[teal])[/teal]
        [b]else[/b][teal]:[/teal]
            before[teal][[/teal]before_index[teal]] =[/teal] line
            before_index [teal]+=[/teal] [purple]1[/purple]
            [b]if[/b] before_index [teal]>[/teal] [COLOR=orange]len[/color][teal]([/teal]before[teal]) -[/teal] [purple]1[/purple][teal]:[/teal]
                before_index [teal]=[/teal] [purple]0[/purple]
        [b]if[/b] [i][green]"FIND"[/green][/i] [b]in[/b] line[teal]:[/teal]
            [b]print[/b][teal]([/teal][i][green]""[/green][/i][teal].[/teal][COLOR=orange]join[/color][teal]([/teal]before[teal][[/teal]before_index[teal]:]) +[/teal] [i][green]""[/green][/i][teal].[/teal][COLOR=orange]join[/color][teal]([/teal]before[teal][:[/teal]before_index[teal]]) +[/teal] [i][green]""[/green][/i][teal].[/teal][COLOR=orange]join[/color][teal]([/teal][COLOR=orange]islice[/color][teal]([/teal]f[teal],[/teal] [purple]4[/purple][teal])))[/teal]

Just for completeness, there would be another way using [tt]islice()[/tt], but due to its inability to handle negative indexes, we rewind the file, so this one does not handle multiple matches :
Python:
[red]from[/red] itertools [red]import[/red] islice

index [teal]=[/teal] [purple]0[/purple]
with [COLOR=orange]open[/color][teal]([/teal]myfile[teal],[/teal] [i][green]"r"[/green][/i][teal])[/teal] as f[teal]:[/teal]
    [b]for[/b] line [b]in[/b] f[teal]:[/teal]
        index [teal]+=[/teal] [purple]1[/purple]
        [b]if[/b] [i][green]"FIND"[/green][/i] [b]in[/b] line[teal]:[/teal]
            f[teal].[/teal][COLOR=orange]seek[/color][teal]([/teal][purple]0[/purple][teal])[/teal]
            [b]print[/b][teal]([/teal][i][green]""[/green][/i][teal].[/teal][COLOR=orange]join[/color][teal]([/teal][COLOR=orange]islice[/color][teal]([/teal]f[teal],[/teal] index [teal]-[/teal] [purple]5[/purple][teal],[/teal] index [teal]+[/teal] [purple]4[/purple][teal])))[/teal]
            [b]break[/b]


Feherke.
feherke.github.io
 
That is awesome!
Now I need to understand it. Thank you for your coaching!
 

To "feherke".

I'm trying to understand your code but it is too much for me for now.
Why this If block is the last block in the script?
Python:
if "FIND" in line:
And this part of the script is totally confusing
Python:
        if (len(before) < 5):
            before.append(line)
        else:
            before[before_index] = line
            before_index += 1
Python:
from itertools import islice

before = []
before_index = 0
with open(myfile, "r") as f:
    for line in f:
        if (len(before) < 5):
            before.append(line)
        else:
            before[before_index] = line
            before_index += 1
            if before_index > len(before) - 1:
                before_index = 0
        if "FIND" in line:
            print("".join(before[before_index:]) + "".join(before[:before_index]) + "".join(islice(f, 4)))

Also, I cannot print lines "before" and lines "after" to a file.
Could you help me please?
Thank you.



 
And the same story with this snippet.
It prints what I need but I need to print it to aa different file.
Have no idea how to print the lines to a file.
Python:
index = 0
with open(myfile, "r") as f:
    for line in f:
        index += 1
        if "FIND" in line:
            f.seek(0)
            print("".join(islice(f, index - 5, index + 4)))
            
            break
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top