Регулярные выражения python - как заменить несколько групп захвата на элементы из списка

Здесь много ответов на регулярное выражение, но ни одна из них не соответствует моей потребности перебирать несколько совпадений и заменять захват последовательными элементами из списка.

Я обыскал официальные документы, но, честно говоря, некоторые объяснения и примеры просто слишком сложны и сложны для меня. До сих пор я разработал, как захватывать несколько групп и называть их, но я зациклился на том, как вставлять в них разные элементы списка.

Пример псевдокода...

for first_match group:
 insert list_item 1

for second_match group:
 insert list_item 2

for third_match group :
 insert list_item 3

Упрощенный пример кода (у моего реального скрипта есть дюжина или более совпадений)

Струна:

"Substitute a **list_item** here, Substitute a **list_item** here, Substitute a **list_item** here"

Регулярное выражение:

\w.*(?P<first_match>list_item)\W.*\W.*(?P<second_match>list_item)\W.*\W.*(?P<third_match>list_item)
</third_match></second_match></first_match>

Список

["first_item", "second_item", "third_item"]

То, что я надеюсь достичь, выглядит следующим образом:

"Substitute a **first_item** here, Substitute a **second_item** here, Substitute a **third_item** here"

Я мог бы также добиться этого с помощью неименованных групп, но именование дает большую удобочитаемость.

2 ответа

Это может быть легко достигнуто с помощью функций start() и end().

import re

string= "Substitute a **list_item** here, Substitute a **list_item** here, Substitute a **list_item** here"
pattern= r'\w.*(?P<first_match>list_item)\W.*\W.*(?P<second_match>list_item)\W.*\W.*(?P<third_match>list_item)'

list= ["first_item", "second_item", "third_item"]


result= ''
i= 0
last_match= 0
match= re.match(pattern, string)
for count in xrange(len(match.groups())): # for each group...
 result+= string[last_match:match.start(i+1)] # add all text up to the start of the group
 result+= list[i] # add the next list item
 last_match= match.end(i+1)
 i+= 1
result+= string[last_match:] # finally, add all text after the last group

print result
</third_match></second_match></first_match>


Почему бы не использовать сопоставление для замены?

def mapping_replace(s):
 import re
 mapping = \ # allows us to continue to the next line
 {
 'first_item': '"Hi there"',
 'second_item': '"waddup"',
 'third_item': '"potato"'
 }

 # for each key in the map
 for key in mapping.iterkeys():
 # replace any 'key' found with the 'value' that corresponds with it
 s = re.sub(r'\b%s\b' % key, mapping[key], s, flags=re.MULTILINE)

 return s

print mapping_replace('first_item substitute a first_item here, a second_item here and a third_item here... first_item') # prints "Hi there" substitute a "Hi there" here, a "waddup" here and a "potato" here "Hi there"

\b проверяет, есть ли граница слова. Если вы не заинтересованы в том, что вы можете просто сопоставить ключ, и тогда не нужно быть пробелом, то есть first_itemyaa увидит first_item и заменит его "Hi there" для "Hi there"yaa

licensed under cc by-sa 3.0 with attribution.