Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > flexible find and replace ?

Reply
Thread Tools

flexible find and replace ?

 
 
OdarR
Guest
Posts: n/a
 
      02-16-2009
Hi guys,

how would you do a clever find and replace, where the value replacing
the tag
is changing on each occurence ?

".......TAG............TAG................TAG..... .....TAG....."

is replaced by this :

".......REPL01............REPL02................RE PL03..........REPL04..."


A better and clever method than this snippet should exist I hope :

counter = 1
while 'TAG' in mystring:
mystring=mystring.replace('TAG', 'REPL'+str(counter), 1)
counter+=1
...

(the find is always re-starting at the string beginning, this is not
efficient.

any ideas ? thanks,

Olivier
 
Reply With Quote
 
 
 
 
bearophileHUGS@lycos.com
Guest
Posts: n/a
 
      02-16-2009
OdarR:

> how would you do a clever find and replace, where the value replacing
> the tag is changing on each occurence ?
> ".......TAG............TAG................TAG..... .....TAG....."
> is replaced by this :
> ".......REPL01............REPL02................RE PL03..........REPL04..."



You may use something like this (tested) replacing XXXXXXXXXXXX with
the correct re function:

import re

def replacer(mobj):
replacer.counter += 1
return "REPL%02d" % replacer.counter
replacer.counter = 0

print re.XXXXXXXXXXXX("TAG", replacer, s1)

(If you have more than 99 replacements it will use more than two
digits.)

Bye,
bearophile
 
Reply With Quote
 
 
 
 
Jason Scheirer
Guest
Posts: n/a
 
      02-16-2009
On Feb 16, 12:10*pm, OdarR <(E-Mail Removed)> wrote:
> Hi guys,
>
> how would you do a clever find and replace, where the value replacing
> the tag
> is changing on each occurence ?
>
> ".......TAG............TAG................TAG..... .....TAG....."
>
> is replaced by this :
>
> ".......REPL01............REPL02................RE PL03..........REPL04..."
>
> A better and clever method than this snippet should exist I hope :
>
> counter = 1
> while 'TAG' in mystring:
> * * mystring=mystring.replace('TAG', 'REPL'+str(counter), 1)
> * * counter+=1
> * * ...
>
> (the find is always re-starting at the string beginning, this is not
> efficient.
>
> any ideas ? thanks,
>
> Olivier


You could split on the string and interleave your new string in
between:

In [1]: def replmaker():
...: index = 0
...: while True:
...: index += 1
...: yield "REPL%02i"%index
...:

In [2]: def spliton(string, tag="TAG", sepgen=replmaker):
...: repl_iter = sepgen()
...: strlist = string.split(tag)
...: length = len(strlist)
...: for index, item in enumerate(strlist):
...: yield item
...: if index < length - 1:
...: yield repl_iter.next()
...:

In [3]: ''.join(spliton
(".......TAG............TAG................TAG.... ......TAG....." ))
Out[3]:
'.......REPL01............REPL02................RE PL03..........REPL04.....'
 
Reply With Quote
 
Tim Chase
Guest
Posts: n/a
 
      02-16-2009
> how would you do a clever find and replace, where the value replacing
> the tag
> is changing on each occurence ?
>
> ".......TAG............TAG................TAG..... .....TAG....."
>
> is replaced by this :
>
> ".......REPL01............REPL02................RE PL03..........REPL04..."




This is a variant of the class I've used in the past for stateful
replacements:

import re

class Counter(object):
def __init__(self, prefix="REPL", start=1):
self.prefix = prefix
self.counter = start - 1
def __call__(self, matchobj):
self.counter += 1
return "%s%02i" % (self.prefix, self.counter)

r = re.compile("TAG") # the regexp to find what we want
s = "some TAG stuff with TAG whatever more TAG stuff"

print s
# just use the counter
print r.sub(Counter(), s)
# demo a different starting number
print r.sub(Counter(start=42), s)
# maintain a single counter across calls
c = Counter(prefix="Hello", start=42)
print r.sub(c, s)
print r.sub(c, s)

> A better and clever method than this snippet should exist I hope :
>
> counter = 1
> while 'TAG' in mystring:
> mystring=mystring.replace('TAG', 'REPL'+str(counter), 1)
> counter+=1
> ...
>
> (the find is always re-starting at the string beginning, this is not
> efficient.


This also has problems if your search-string is a substring of
your replacement string:

search = "foo"
replacement = "foobar#"

You'll get

s = "foo_foo"
s = "foobar01_foo"
s = "foobar02bar01_foo"
...

which isn't quite what it looks like you want.

-tkc



 
Reply With Quote
 
John Machin
Guest
Posts: n/a
 
      02-17-2009
On Feb 17, 7:10*am, OdarR <(E-Mail Removed)> wrote:
> Hi guys,
>
> how would you do a clever find and replace, where the value replacing
> the tag
> is changing on each occurence ?
>
> ".......TAG............TAG................TAG..... .....TAG....."
>
> is replaced by this :
>
> ".......REPL01............REPL02................RE PL03..........REPL04..."
>
> A better and clever method than this snippet should exist I hope :
>
> counter = 1
> while 'TAG' in mystring:
> * * mystring=mystring.replace('TAG', 'REPL'+str(counter), 1)
> * * counter+=1
> * * ...
>
> (the find is always re-starting at the string beginning, this is not
> efficient.
>
> any ideas ? thanks,


C:\junk>type fancyrepl.py
def fancyrepl(tag, replfunc, input_string):
count = 0
pieces = []
pos = 0
taglen = len(tag)
while 1:
try:
newpos = input_string.index(tag, pos)
except ValueError:
pieces.append(input_string[pos:])
return ''.join(pieces)
pieces.append(input_string[pos:newpos])
count += 1
pieces.append(replfunc(count))
pos = newpos + taglen

tests = [
'',
'XXX',
'XXXXXX',
'abcdeXXX',
'XXXfghij',
'abcdeXXXfghij',
'abcdeXXXfghijXXXpqrst',
]

for test in tests:
print ' <', repr(test)
result = fancyrepl('XXX', lambda n: 'SUB%d' % n, test)
print ' >', repr(result)

C:\junk>fancyrepl.py
< ''
> ''

< 'XXX'
> 'SUB1'

< 'XXXXXX'
> 'SUB1SUB2'

< 'abcdeXXX'
> 'abcdeSUB1'

< 'XXXfghij'
> 'SUB1fghij'

< 'abcdeXXXfghij'
> 'abcdeSUB1fghij'

< 'abcdeXXXfghijXXXpqrst'
> 'abcdeSUB1fghijSUB2pqrst'


HTH,
John


 
Reply With Quote
 
Gerard Flanagan
Guest
Posts: n/a
 
      02-17-2009
OdarR wrote:
> Hi guys,
>
> how would you do a clever find and replace, where the value replacing
> the tag
> is changing on each occurence ?
>
> ".......TAG............TAG................TAG..... .....TAG....."
>
> is replaced by this :
>
> ".......REPL01............REPL02................RE PL03..........REPL04..."
>
>
> A better and clever method than this snippet should exist I hope :
>
> counter = 1
> while 'TAG' in mystring:
> mystring=mystring.replace('TAG', 'REPL'+str(counter), 1)
> counter+=1
> ...
>
> (the find is always re-starting at the string beginning, this is not
> efficient.
>
> any ideas ? thanks,
>


The first thing that comes to mind is re.sub:

import re

def replace(s, patt, repls):
def onmatch(m):
onmatch.idx += 1
return repls[onmatch.idx]
onmatch.idx = -1
return patt.sub(onmatch, s)

test = """
abcTAG TAG asdTAGxyz
"""

REPLS = [
'REPL1',
'REPL2',
'REPL3',
]

print replace(test, re.compile('TAG'), REPLS)

 
Reply With Quote
 
Gerard Flanagan
Guest
Posts: n/a
 
      02-17-2009
Gerard Flanagan wrote:
>
> def replace(s, patt, repls):
> def onmatch(m):
> onmatch.idx += 1
> return repls[onmatch.idx]
> onmatch.idx = -1
> return patt.sub(onmatch, s)
>


> test = """
> abcTAG TAG asdTAGxyz
> """
>
> REPLS = [
> 'REPL1',
> 'REPL2',
> 'REPL3',
> ]
>
> print replace(test, re.compile('TAG'), REPLS)
>
> --


or better:

import re

def replace(s, patt, repls):
repls = iter(repls)
return patt.sub(lambda m: repls.next(), s)

test = """
abcTAG TAG asdTAGxyz
"""

def repls(tag):
i = 0
while True:
i += 1
yield tag + str(i)

print replace(test, re.compile('TAG'), repls('REPL'))

 
Reply With Quote
 
John Machin
Guest
Posts: n/a
 
      02-17-2009
On Feb 17, 7:18*pm, Duncan Booth <(E-Mail Removed)> wrote:
> John Machin <(E-Mail Removed)> wrote:
> > def fancyrepl(tag, replfunc, input_string):
> > * * count = 0
> > * * pieces = []
> > * * pos = 0
> > * * taglen = len(tag)
> > * * while 1:
> > * * * * try:
> > * * * * * * newpos = input_string.index(tag, pos)
> > * * * * except ValueError:
> > * * * * * * pieces.append(input_string[pos:])
> > * * * * * * return ''.join(pieces)
> > * * * * pieces.append(input_string[pos:newpos])
> > * * * * count += 1
> > * * * * pieces.append(replfunc(count))
> > * * * * pos = newpos + taglen

>
> Or even:
>
> import re, itertools
> def fancyrepl(tag, replfunc, input_string):
> * * * * counter = itertools.count(1)
> * * * * return re.sub(re.escape(tag),
> * * * * *lambda m: replfunc(counter.next()), input_string)
>
> which does exactly the same thing


Not exactly; mine needs
taglen = max(1, len(tag))
to stop an infinite loop when len(tag) == 0.

> in rather less code.


and with rather less execution speed [measured at about half] and
rather less OP-explanation speed [guessed]
 
Reply With Quote
 
OdarR
Guest
Posts: n/a
 
      02-17-2009
Thanks to everybody.
I need to test your propositions now

Olivier
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Verbose and flexible args and kwargs syntax Eelco Hoogendoorn Python 88 12-17-2011 08:02 PM
Verbose and flexible args and kwargs syntax Eelco Hoogendoorn Python 1 12-11-2011 10:19 PM
Verbose and flexible args and kwargs syntax Eelco Hoogendoorn Python 0 12-11-2011 02:58 PM
Verbose and flexible args and kwargs syntax Eelco Hoogendoorn Python 0 12-11-2011 02:44 PM
Compiler error occurred when try to use a flexible template expression in preprocessor definesCompiler error occurred when try to use a flexible template expression in preprocessor defines snnn C++ 6 03-14-2005 04:09 PM



Advertisments