0

After finding a specific line with keyword "banana", I would like to delete the subsequent line, in this case, "berry".

Sample.txt

orange
apple
banana
berry
melon

My script, however, deletes "banana" not "berry"....Why?

import fileinput

filename = r"C:\sample.txt"
for linenum,line in enumerate(fileinput.FileInput(filename, inplace=1)):
    if "banana" in line:
        counter = linenum + 1
        if linenum == counter:
            line.strip()
    else:
        print line,
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
fairyberry
  • 1,125
  • 1
  • 11
  • 13
  • first of all, this script never deletes anything, in fact, what i can see is that it prints any line in the file, unless 'banana' is in the line, in which case it increases a counter and then strips whitespace from the end of the current line.... i suggest you read up on your python skills, because this is not doing anything. – Inbar Rose Jan 14 '13 at 08:43
  • @inbar: it does delete the line with the keyword. – fairyberry Jan 14 '13 at 08:48
  • Do you mean `filter` when you say `delete`? – Burhan Khalid Jan 14 '13 at 09:06
  • comment made by @Inbar Rose is valid. The flaw in your code is that you're not deleting anything. In fact you're actually rewriting the whole file. You're re-printing all lines except for the one that has "banana" in it. And inplace=1 is allowing you to do that. – tigeronk2 Jan 14 '13 at 10:13
  • @InbarRose In this case, it is you who should read up on your python skills. Try the answer (and comments) [here](http://stackoverflow.com/a/290494/674039) for example. – wim Jan 15 '13 at 15:04

3 Answers3

3

Do it like this:

import fileinput

fin = fileinput.input('/home/jon/text.txt', inplace=1)
for line in fin:
    print line,
    if line.strip() == 'banana':
        next(fin, None) # as suggested by @thg435 doesn't hurt to use default to avoid StopIteration (as next iteration will just be a no-op anyway)

This takes advantage of iterating the fin object so it doesn't see the next row - meaning you don't have to worry about setting/unsetting flags... (which can lead to errors)

Jon Clements
  • 138,671
  • 33
  • 247
  • 280
2

Something like this:

flag = False
with open("C:\sample.txt") as in_f:
    for line in in_f:
        if flag: # previous line have "banana", so skip this line
            flag = False
            continue
        if "banana" in line: # set flag to skip line
            flag = True
        print line
cleg
  • 4,862
  • 5
  • 35
  • 52
  • 1
    Change the __pring__ to `print` – Matthias Jan 14 '13 at 08:53
  • @cleg: thanks for the advice. I never knew you could use the "flag" like that. Good learning experience. Thanks again. – fairyberry Jan 14 '13 at 08:59
  • @Inbar: I see. Good observation. Though, as long as I can print out all the lines except the one I want to delete, then it would help me to rewrite the file except the one. Thanks. – fairyberry Jan 14 '13 at 09:11
  • @user1027101 you're welcome. it's common practice actually. BTW, it's very-very simple example of finite state machine — mechanism, used for parsers and comliers :) – cleg Jan 14 '13 at 09:11
  • @user1027101 also, often use "skipping" instead of "deleting" — is also a solution – cleg Jan 14 '13 at 09:12
1

Please try this

filename = r"sample.txt"
counter = -1
for linenum,line in enumerate(fileinput.FileInput(filename, inplace=1)):
    if "banana" in line:
        counter = linenum + 1
    if linenum == counter:
        line.strip()
    else:
        print line,
fwu
  • 359
  • 2
  • 10