Sergio135153
Sergio135153

Reputation: 19

Can you delete all the lines of a .txt file after a specific line?

I am trying to delete all the lines in a text file after a line that contains a specific string. What I am trying to do is find the number of the line in said file and rewrite the whole text up until that line.

The code that I'm trying is the following:

import itertools as it
with open('sampletext.txt', "r") as rf:
    for num, line in enumerate(rf, 1): #Finds the number of the line in which a specific string is contained
        if 'string' in line:
            print(num)
    with open('sampletext_copy.txt', "w") as wf:
        for line in it.islice(rf, 0, num):
            wf.write(line)

Also would appreciate any tips on how to do this. Thank you!

Upvotes: 1

Views: 1523

Answers (3)

ShadowRanger
ShadowRanger

Reputation: 155428

Just to complement Donut's answer, if you want to modify the file in-place, there's a much more efficient solution:

with open('sampletext.txt', "r+") as f:
    for line in iter(f.readline, ''):  # Can't use for line in f: because it disables
                                       # tell for txt
    # Or for walrus lovers:
    # while line := f.readline():
        if 'string' in line:
            f.seek(0, 1)  # Needed to ensure underlying handle matches logical read
                          # position; f.seek(f.tell()) is logically equivalent
            f.truncate()
            break

If issue #70346 is ever fixed (so calling truncate on a file actually truncates at the logical position, not the arbitrary position of the underlying raw handle that's likely advanced a great deal due to buffering), this simpler code would work:

with open('sampletext.txt', "r+") as f:
    for line in f:
        if 'string' in line:
            f.truncate()
            break

If you want to delete the tested-for line as well, not just the following lines, you need to store the cookie before reading each line so you can back up when you find it (sticking to walrus this time, since most people can probably use it by now):

with open('sampletext.txt', "r+") as f:
    cookie = 0  # Don't need tell to seek back to start of file if first line matches
    while line := f.readline():
        if 'string' in line:
            f.seek(cookie)  # Revert to position before we read in most recent line
            f.truncate()
            break
        cookie = f.tell()   # Save off position cookie prior to reading next line

Upvotes: 1

Olvin Roght
Olvin Roght

Reputation: 7812

In case if you want to apply changes to original file, it's possible to do using .truncate() method of file object:

with open(r"sampletext.txt", "r+") as f:
    while line := f.readline():
        if line.rstrip() == "string":  # line.startswith("string")
            f.truncate(f.tell())  # removes all content after current position
            break

Here we iterating over file until reach this specific line and resize stream to size of bytes we've already read (to get it we use .tell()).

Upvotes: 0

Donut
Donut

Reputation: 112825

You could do it like this:

with open('sampletext.txt', "r") as rf, open('sampletext_copy.txt', "w") as wf:
    for line in rf:
        if 'string' in line:
            break
        wf.write(line)

Basically, you open both files at the same time, then read the input file line-by-line. If string is in the line, then you're done - otherwise, write it to the output file.

Upvotes: 2

Related Questions