0

I have a text file which contains the following:

NUM,123
FRUIT
DRINK
FOOD,BACON
CAR
NUM,456
FRUIT
DRINK
FOOD,BURGER
CAR
NUM,789
FRUIT
DRINK
FOOD,SAUSAGE
CAR

I'm trying to change BURGER but how to do that?

file = open('input.txt', 'r')
while True:
    line = file.readline()
    if '456' in line:
        print line
        break

With the above code, I want to pinpoint it using the distinct number after NUM, but I am only able to read the line where 456 occurs. How to read 3 lines below 456 and then access the BURGER part?

Thanks!

Update using Levon's solution:

with open('input.txt','r') as f:
    data = f.readlines()
    for i, line in enumerate(data):
        if '456' in line:
            field = ','.join(data[i+3].split(',')[1])
            field = field.replace(field,'PIZZA')

Now how do you write everything back into a new file?

user1546610
  • 175
  • 5
  • 13

3 Answers3

2

Update based on comment below:

Use this code if all of the file can fit into memory (reads all of file at once):

with open("data.txt") as f:
    data = f.readlines()
    for i, line in enumerate(data):
        if "456" in line:
            print data[i+3].split(',')[1],

We read the whole file into a list (data), and then use enumerate() to access both the index (i), and the element at the given index (ie. the line). Since we have all of the data in the list, once we find the line with "456" we can look for the line at i + 3 very easily in our list and use split() to separate out the word we are interested in.

--

Use this code if file is potentially very big (processes file line-by-line):

with open("data.txt") as f:
    count = -1
    for line in f:
        if "456" in line:
            count = 4

        count -= 1
        if count == 0:
            print line.split(',')[1],

will print "BURGER"

This looks for the 2nd word, 3 lines after the string "456". It assumes the words are separated by a comma (,)

Note that using the with construct also takes care of closing the file when we are done (or if we encounter an exception).

Levon
  • 138,105
  • 33
  • 200
  • 191
  • In your case you pinpoint it with the "BURGER", what I'm trying to do is to pinpoint it with the "456" and then read 3 lines below it and replace the "second word" which is "BURGER" – user1546610 Aug 22 '12 at 00:00
  • @user1546610 So you are looking for the 2nd word 3 lines *after* you see the string "456"? But you don't necessarily want to change that string, correct? – Levon Aug 22 '12 at 00:01
  • @user1546610 Do you just want to print/access that particular string, and nothing else? – Levon Aug 22 '12 at 00:02
  • Yes printing/accessing that one would be fine. Thanks. – user1546610 Aug 22 '12 at 00:05
  • +1, and there's no use overcomplicating things for beginners (I'd use csv/itertools to make a record grouper :^) -- but I always wince a little when I see the 'string in otherstring' construct because of the problem of "NUM,4567". – DSM Aug 22 '12 at 00:27
  • @DSM agreed, the "string `in` otherstring" definitely has its limitations/drawbacks, but seemed to work fine here. – Levon Aug 22 '12 at 00:30
  • Great update Levon! Now how do you write everything (updated) back to a new file? – user1546610 Aug 22 '12 at 22:30
  • @user1546610 I don't know what you upated :) .. but assuming you changed something in `data` you could write the `data` back this way: `with open('result.txt', 'w') as outfp: outfp.write(''.join(data))` (note the 2nd line is indented below while `with` similarly as above. The output file will be `result.txt`.If this doesn't help, you may want to consider posting a separate/new question. – Levon Aug 22 '12 at 22:34
  • I updated my code. If I do like your comment above then it will just write everything back the same like the original file. – user1546610 Aug 22 '12 at 22:41
0

Try:

file = open('input.txt', 'r')
for line in file.readlines():
    if '456' in line:
        stored_line = line
    if 'BURGER' in line:
        print stored_line

This will give you the correct line in the file and you will have access to the number preceding it. To edit the file in place, look to a solution like this.

If you are just interested in the text stream. You can you add line.replace('BURGER', 'FOO') after the print.

Community
  • 1
  • 1
cmh
  • 10,612
  • 5
  • 30
  • 40
0

Your text file has structure. I presume you are really asking for a way to read that structure, for example so that someone is able to change their order to a pizza.

Your input.txt has some orders. Each order starts with an order number (NUM,456 etc.), then some items, then CAR as if to show that the person in drive through has finished with their order.

So, step 1.

# changes order 456's food to a pizza, from whatever it was
file = open('input.txt', 'r')

bad_order = 'NUM,%d' % 456
new_food = 'FOOD,%s' % 'Pizza'

change = False
for line in file:
  line = line.strip()
  msg = ''
  if line.startswith('NUM,'):
    msg = 'Ignoring order: '
  if line == bad_order:
    msg = 'Changing order: '
    change = True
  if change and line.startswith('FOOD,'):
    line = new_food
  if line == 'CAR':
    change = False
  print '%s%s' % (msg, line)

Further steps might be to recognize the structure more formally (eg add orders to a collection for processing later); or refactor this into a function so you can test changing different order numbers and different food types, not just FOOD.

EDIT

I've edited the code to make it clear how it currently reads your file. The output is now:

Ignoring order: NUM,123
FRUIT
DRINK
FOOD,BACON
CAR
Changing order: NUM,456
FRUIT
DRINK
FOOD,Pizza
CAR
Ignoring order: NUM,789
FRUIT
DRINK
FOOD,SAUSAGE
CAR
azhrei
  • 2,303
  • 16
  • 18