2012-09-26 9 views
32

mam ciąg w Pythonie, powiedzmy The quick @red fox jumps over the @lame brown dog.Python zastąpić wzór ciąg z wyjściem funkcji

próbuję zastąpić każde z tych słów, które rozpoczynają się @ z wyjściem funkcję, która pobiera jako słowo argument.

def my_replace(match): 
    return match + str(match.index('e')) 

#Psuedo-code 

string = "The quick @red fox jumps over the @lame brown dog." 
string.replace('@%match', my_replace(match)) 

# Result 
"The quick @red2 fox jumps over the @lame4 brown dog." 

Czy istnieje sprytny sposób na zrobienie tego?

+1

to, co masz, jest dobre. robisz to w jednym komunikacie. – tuxuday

Odpowiedz

58

Możesz przekazać funkcję do re.sub. Funkcja otrzyma obiekt dopasowania jako argument, użyj .group(), aby wyodrębnić dopasowanie jako ciąg znaków.

>>> def my_replace(match): 
...  match = match.group() 
...  return match + str(match.index('e')) 
... 
>>> re.sub(r'@\w+', my_replace, string) 
'The quick @red2 fox jumps over the @lame4 brown dog.' 
+1

Piękny. Nie wiedziałem, że mogę przekazać funkcję re.sub, ale czułem, że powinienem być w stanie. – nathancahill

1

Spróbuj:

import re 

match = re.compile(r"@\w+") 
items = re.findall(string) 
for item in items: 
    string = string.replace(item, my_replace(item) 

To pozwoli Ci wymienić wszystko, co zaczyna się od @ ze cokolwiek wyjście swojej funkcji jest. Nie bardzo wiedziałem, czy potrzebujesz pomocy również z tą funkcją. Daj mi znać, jeśli tak jest.

+0

're.findall (pattern, string)' - napraw to –

+0

Jest to całkiem przydatne, ponieważ pozwala na zamianę tylko dopasowanych elementów w łańcuchu. – Dannid

0

Krótki jeden z regex i zmniejszają:

>>> import re 
>>> pat = r'@\w+' 
>>> reduce(lambda s, m: s.replace(m, m + str(m.index('e'))), re.findall(pat, string), string) 
'The quick @red2 fox jumps over the @lame4 brown dog.' 
4

nie byłem świadomy można przekazać funkcję do re.sub() albo. Riffing na odpowiedź @Janne Karila w celu rozwiązania problemu, który miałem, podejście działa również dla wielu grup przechwytujących.

import re 

def my_replace(match): 
    match1 = match.group(1) 
    match2 = match.group(2) 
    match2 = match2.replace('@', '') 
    return u"{0:0.{1}f}".format(float(match1), int(match2)) 

string = 'The first number is [email protected], and the second number is [email protected]' 
result = re.sub(r'([0-9]+.[0-9]+)(@[0-9]+)', my_replace, string) 

print(result) 

wyjściowa:

The first number is 14.2, and the second number is 50.6000.

Ten prosty przykład wymaga, aby wszystkie grupy przechwytywania być obecny (bez opcjonalnych grup).