2

I am new to python so excuse my ignorance.

Currently, I have a text file with some words marked as <>.

My goal is to essentially build a script which runs through a text file with such marked words. Each time the script finds such a word, it would ask the user for what it wants to replace it with.

For example, if I had a text file:

Today was a <<feeling>> day.

The script would run through the text file so the output would be:

Running script...
feeling? great
Script finished.

And generate a text file which would say:

Today was a great day.

Advice?

Edit: Thanks for the great advice! I have made a script that works for the most part like I wanted. Just one thing. Now I am working on if I have multiple variables with the same name (for instance, "I am <>. Bob is also <>.") the script would only prompt, feeling?, once and fill in all the variables with the same name.

Thanks so much for your help again.

Shayon Saleh
  • 419
  • 3
  • 7
  • 15
  • [http://stackoverflow.com/questions/39086/search-and-replace-a-line-in-a-file-in-python](http://stackoverflow.com/questions/39086/search-and-replace-a-line-in-a-file-in-python) – Kracekumar Jun 28 '11 at 19:39

5 Answers5

8
import re
with open('in.txt') as infile:
    text = infile.read()
search = re.compile('<<([^>]*)>>')
text = search.sub(lambda m: raw_input(m.group(1) + '? '), text)
with open('out.txt', 'w') as outfile:
    outfile.write(text)
phihag
  • 278,196
  • 72
  • 453
  • 469
  • great solution, but it might ruin the learning experience for someone new to python. EDIT: Scratch that, I realized how horrible this would be using ordinary string comparison + replacements! – Dog eat cat world Jun 28 '11 at 19:57
1

To open a file and loop through it:

Use raw_input to get input from user

Now, put this together and update you question if you run into problems :-)

Fredrik Pihl
  • 44,604
  • 7
  • 83
  • 130
1

I understand you want advice on how to structure your script, right? Here's what I would do:

  1. Read the file at once and close it (I personally don't like to have open file objects, especially if my filesystem is remote).
  2. Use a regular expression (phihag has suggested one in his answer, so I won't repeat it) to match the pattern of your placeholders. Find all of your placeholders and store them in a dictionary as keys.
  3. For each word in the dictionary, ask the user with raw_input (not just input). And store them as values in the dictionary.
  4. When done, parse your text substituting any instance of a given placeholder (key) with the user word (value). This is also done with regex.

The reason for using a dictionary is that a given placeholder could occur more than once and you probably don't want to make the user repeat the entry over and over again...

Community
  • 1
  • 1
mac
  • 42,153
  • 26
  • 121
  • 131
1

Basically the same solution as that offerred by @phihag, but in script form

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import argparse
import re
from os import path

pattern = '<<([^>]*)>>'

def user_replace(match):
    return raw_input('%s? ' % match.group(1))


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('infile', type=argparse.FileType('r'))
    parser.add_argument('outfile', type=argparse.FileType('w'))
    args = parser.parse_args()

    matcher = re.compile(pattern)

    for line in args.infile:
        new_line = matcher.sub(user_replace, line)
        args.outfile.write(new_line)

    args.infile.close()
    args.outfile.close()

if __name__ == '__main__':
    main()

Usage: python script.py input.txt output.txt

Note that this script does not account for non-ascii file encoding.

holdenweb
  • 33,305
  • 7
  • 57
  • 77
Rob Cowie
  • 22,259
  • 6
  • 62
  • 56
  • This is what I ended up following. Thanks so much. But I added an edit above which I was wondering about. Right now, the script asks for user input for each variable. If I have the same variable multiple times within the input, could I ask the user only once for the input and fill in all the variables with the given input? – Shayon Saleh Jun 29 '11 at 14:28
0

Try something like this

lines = []
with open(myfile, "r") as infile:
    lines = infile.readlines()

outlines = []
for line in lines:
    index = line.find("<<")
    if index > 0:
        word = line[index+2:line.find(">>")]
        input = raw_input(word+"? ")
        outlines.append(line.replace("<<"+word+">>", input))
    else:
        outlines.append(line)

with open(outfile, "w") as output:
    for line in outlines:
        outfile.write(line)

Disclaimer: I haven't actually run this, so it might not work, but it looks about right and is similar to something I've done in the past.

How it works:

  • It parses the file in as a list where each element is one line of the file.
  • It builds the output list of lines. It iterates through the lines in the input, checking if the string << exist. If it does, it rips out the word inside the << and >> brackets, using it as the question for a raw_input query. It takes the input from that query and replaces the value inside the arrows (and the arrows) with the input. It then appends this value to the list. If it didn't see the arrows it simply appended the line.
  • After running through all the lines, it writes them to the output file. You can make this whatever file you want.

Some issues:

  1. As written, this will work for only one arrow statement per line. So if you had <<firstname>> <<lastname>> on the same line it would ignore the lastname portion. Fixing this wouldn't be too hard to implement - you could place a while loop using the index > 0 statement and holding the lines inside that if statement. Just remember to update the index again if you do that!
  2. It iterates through the list three times. You could likely reduce this to two, but if you have a small text file this shouldn't be a huge problem.
  3. It could be sensitive to encoding - I'm not entirely sure about that however. Worst case there you need to cast as a string.

Edit: Moved the +2 to fix the broken if statement.

thegrinner
  • 11,546
  • 5
  • 41
  • 64