3

Say I had an input file (temp.tmpl) that looked like this:

PTF @
ARB @ C @ @ A @ @ C @
OSN @ B @ @ A @ 
SDA @ B @
CPN 3.23
SNL 3.26 

And in some other file (candidate.txt):

A 3.323 B 4.325 C 6.32 D 723 E 8 F 9 G 1.782
H 7
I 4
J 9
K 10

And I wanted to replace A, B , and C with their assigned values. The way this needs to be accomplished for my task is by finding the variables A, B, and C by looking for @ @...Then knowing this is obviously a varible. Then replacing them. This is what I have tried:

reader = open('candidate.txt', 'r')
out = open('output.txt', 'w')

dictionary = dict()
for line in reader.readlines():
    pairs = line.split()
    for variable, value in zip(pairs[::2],pairs[1::2]):
        dictionary[variable] = value

#Now to open the template file
template = open('temp.tmpl', 'r')
for line1 in template:
    if line1[1]:
        confirm = line1.split(' ')[0].lower()
        symbol = line1.split(' ')[1]

        if confirm == 'ptf':
            next(template)

        elif symbol in line1:

            start = line1.find(symbol)+len(symbol)
            end = line1[start:].find(symbol)
            variable = line1[start:start + end].strip()
            print variable

And I can not seem to figure out how to handle the lines with multiple sets of variables.
Thank you so much in advance.

3
  • Looks like regular expressions can be useful in this case. Commented Jul 3, 2012 at 7:59
  • Did you try using a regular expression with re.sub? Commented Jul 3, 2012 at 8:01
  • Remember to close your file handles. Commented Jul 3, 2012 at 9:08

2 Answers 2

2

Using an re? The question was altered, and here is my modified solution:

import re

# Create translation dictionary
codes = re.split(r'\s',open('candidate.txt').read())
trans = dict(zip(codes[::2], codes[1::2]))

outfh = open('out.txt','w')
infh  = open('data.txt')

# First line contains the symbol, but has a trailing space!
symbol = re.sub(r'PTF (.).*',r'\1', infh.readline()[:-1])

for line in infh:
    line = re.sub('\\'+ symbol + r' ([ABC]) ' + '\\' + symbol,
               lambda m: '%s %s %s' % (symbol,trans[m.groups()[0]],symbol),
               line)
    outfh.write(line) 

outfh.close()

The dict using two zips is a trick to create a dictionary from a [key,value,key,value,...] list

trans is a dictionary with the names and their respective values.
r'@ ([ABC]) @' captures either A or B or C within the @ signs The lambda function is passed a match object, on which we are calling the groups() method. This returns a tuple of the matching parentheses groups, in this case either A or B or C. We use this for the key to the dictionary trans, and hence replace it with the value.

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you for your post because it really helps and im learning a good bit about re's now, but how would the syntax change if from the first line of the input file, @ was defined as symbol and now everywhere in your code, @ was replaced by the variable 'symbol'...could this still work ?
Yes, provided the symbol was not an RE meta-character (special character) like * or . or [ or { or + or ? and so on. If in doubt, place a \ to its left. This also applies if the symbol if held in a variable.
hmmm...let me edit my original post to include everything i am trying to do
On further consideration, look-arounds could simplify the lambda (but make the re more complex)
1

Wouldn't simple string replacement work for you?

>>> 'foo @ A @ @ B @'.replace('@ A @','12345')
'foo 12345 @ B @'

It will replace all occurrences of @ A @ to whatever you want. You can apply it multiple times, perhaps once for every variable:

# a dictionary of variable values,
# you'll probably read this from somewhere
values = { 'A': '123', 'B': '456' }

# iterate over variable names
for varname in values: 
    pattern = str.format('@ {} @', varname)
    value = values[varname]

    # data is your input string
    data = data.replace(pattern, value)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.