2

I have a file like this (this is a simplified version):

james sfsf qef qef
qef qef qe fff
qqew james james qef
qefq ffgrsf wsef 
qef james eq james

I want to replace each iteration of 'james' with a different value. Here's what I have in my test code:

f=open('file_to_be_read.txt','r')
text=f.read()
matches=len(re.findall('james',text))
f.close()
number=0
for x in range(matches):
    new_text=re.sub(r'james',str(number),text,count=1)
    number+=1
r=open('result_file.txt','w')
r.write(new_text)
r.close()

But it just replaces the first 'james' with 2. Rather than produce the following result that I want:

1 sfsf qef qef
qef qef qe fff
qqew 2 3 qef
qefq ffgrsf wsef 
qef 4 eq 5

I thought that by repeating the re.sub with count=1 I would replace 1 james each time but allow me to change the replace value.

2
  • "But it just replaces the first 'james' with 2". Strange. It replaces it with "4" on my machine. Commented Aug 24, 2015 at 12:43
  • You're right, in typing it up I changed my example file I was reading from. Commented Aug 24, 2015 at 12:51

4 Answers 4

6

I would recommend using itertools.count for this:

>>> from itertools import count
>>> import re
>>> s = '''james sfsf qef qef
qef qef qe fff
qqew james james qef
qefq ffgrsf wsef
qef james eq james'''
>>> print re.sub(r'james', lambda x, c=count(1): str(next(c)), s)
1 sfsf qef qef
qef qef qe fff
qqew 2 3 qef
qefq ffgrsf wsef
qef 4 eq 5

Here c=count(1) is a default argument value and it is going to be calculated only once(when the function object is created), next calls to this function are going to increment the previous count each time.

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

1 Comment

Thanks. I accepted another one because it was closer to the way I was doing it, but it's always nice to see more efficient solutions too.
2

you're discarding the updated string - try this:

text = re.sub(r'james', str(x), text, count=1)

1 Comment

Thanks, that was a silly mistake by me. Sometimes I can't see the wood for the trees.
0
new_text=re.sub(r'james',str(number),text,count=1)

You are working on text each time. You give it the same input text to work with, rather than processing your new_text.

Try this:

new_text = text
for x in range(matches):
    new_text=re.sub(r'james',str(number),new_text,count=1)
    number+=1
number+=1

Comments

0

re.sub can take a function as the replacement value. This does roughly what you want

import re

with open('file_to_be_read.txt', 'r') as f:
    text = f.read()

number = 0
def do_replace( matchobj ):
    global number
    replacement = str(number)
    number += 1
    return replacement

new_text = re.sub(r'james', do_replace, text)

with open('result_file.txt', 'w') as r:
    r.write(new_text)

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.