[python] 문자열의 여러 하위 문자열을 바꾸는 방법은 무엇입니까?

.replace 함수를 사용하여 여러 문자열을 바꾸고 싶습니다.

나는 현재

string.replace("condition1", "")

하지만 같은 것을 갖고 싶습니다

string.replace("condition1", "").replace("condition2", "text")

좋은 문법처럼 보이지는 않지만

이를 수행하는 올바른 방법은 무엇입니까? grep / regex에서 어떻게 할 수 \1있고 \2필드를 특정 검색 문자열로 바꾸는 것과 같은 종류



답변

다음은 정규 표현식으로 트릭을 수행해야하는 간단한 예입니다.

import re

rep = {"condition1": "", "condition2": "text"} # define desired replacements here

# use these three lines to do the replacement
rep = dict((re.escape(k), v) for k, v in rep.iteritems())
#Python 3 renamed dict.iteritems to dict.items so use rep.items() for latest versions
pattern = re.compile("|".join(rep.keys()))
text = pattern.sub(lambda m: rep[re.escape(m.group(0))], text)

예를 들면 다음과 같습니다.

>>> pattern.sub(lambda m: rep[re.escape(m.group(0))], "(condition1) and --condition2--")
'() and --text--'


답변

멋진 작은 루핑 기능을 만들 수 있습니다.

def replace_all(text, dic):
    for i, j in dic.iteritems():
        text = text.replace(i, j)
    return text

여기서 text완전한 문자열 dic은 사전이며 각 정의는 용어와 일치하는 문자열을 대체합니다.

참고 : Python 3에서는 다음 iteritems()으로 대체되었습니다.items()


주의 : 파이썬 사전은 신뢰할만한 반복 순서가 없습니다. 이 솔루션은 다음과 같은 경우에만 문제를 해결합니다.

  • 교체 순서는 관련이 없습니다.
  • 교체가 이전 교체의 결과를 변경해도 괜찮습니다.

예를 들어 :

d = { "cat": "dog", "dog": "pig"}
my_sentence = "This is my cat and this is my dog."
replace_all(my_sentence, d)
print(my_sentence)

가능한 출력 # 1 :

"이것은 나의 돼지이고 이것은 나의 돼지입니다."

가능한 출력 # 2

"이것은 나의 개이고 이것은 나의 돼지입니다."

하나의 가능한 수정은 OrderedDict를 사용하는 것입니다.

from collections import OrderedDict
def replace_all(text, dic):
    for i, j in dic.items():
        text = text.replace(i, j)
    return text
od = OrderedDict([("cat", "dog"), ("dog", "pig")])
my_sentence = "This is my cat and this is my dog."
replace_all(my_sentence, od)
print(my_sentence)

산출:

"This is my pig and this is my pig."

주의 # 2 :text 문자열이 너무 크거나 사전에 많은 쌍이있는 경우 비효율적 입니다.


답변

왜 이런 해결책이 없습니까?

s = "The quick brown fox jumps over the lazy dog"
for r in (("brown", "red"), ("lazy", "quick")):
    s = s.replace(*r)

#output will be:  The quick red fox jumps over the quick dog


답변

다음은 기능을 좋아하는 경우 reduce를 사용하는 첫 번째 솔루션의 변형입니다. 🙂

repls = {'hello' : 'goodbye', 'world' : 'earth'}
s = 'hello, world'
reduce(lambda a, kv: a.replace(*kv), repls.iteritems(), s)

마르티노의 더 나은 버전 :

repls = ('hello', 'goodbye'), ('world', 'earth')
s = 'hello, world'
reduce(lambda a, kv: a.replace(*kv), repls, s)


답변

이것은 FJ와 MiniQuark의 훌륭한 답변을 간결하게 요약 한 것입니다. 여러 개의 동시 문자열 대체 를 달성하기 위해 필요한 것은 다음 기능입니다.

def multiple_replace(string, rep_dict):
    pattern = re.compile("|".join([re.escape(k) for k in sorted(rep_dict,key=len,reverse=True)]), flags=re.DOTALL)
    return pattern.sub(lambda x: rep_dict[x.group(0)], string)

용법:

>>>multiple_replace("Do you like cafe? No, I prefer tea.", {'cafe':'tea', 'tea':'cafe', 'like':'prefer'})
'Do you prefer tea? No, I prefer cafe.'

원하는 경우이 간단한 것부터 시작하여 고유 한 전용 교체 기능을 만들 수 있습니다.


답변

나는 이것을 FJ의 훌륭한 답변을 바탕으로 구축했습니다.

import re

def multiple_replacer(*key_values):
    replace_dict = dict(key_values)
    replacement_function = lambda match: replace_dict[match.group(0)]
    pattern = re.compile("|".join([re.escape(k) for k, v in key_values]), re.M)
    return lambda string: pattern.sub(replacement_function, string)

def multiple_replace(string, *key_values):
    return multiple_replacer(*key_values)(string)

원샷 사용법 :

>>> replacements = (u"café", u"tea"), (u"tea", u"café"), (u"like", u"love")
>>> print multiple_replace(u"Do you like café? No, I prefer tea.", *replacements)
Do you love tea? No, I prefer café.

교체는 한 번만 수행되므로 “café”는 “tea”로 변경되지만 “café”로 다시 변경되지는 않습니다.

동일한 교체를 여러 번 수행해야하는 경우 교체 기능을 쉽게 만들 수 있습니다.

>>> my_escaper = multiple_replacer(('"','\\"'), ('\t', '\\t'))
>>> many_many_strings = (u'This text will be escaped by "my_escaper"',
                       u'Does this work?\tYes it does',
                       u'And can we span\nmultiple lines?\t"Yes\twe\tcan!"')
>>> for line in many_many_strings:
...     print my_escaper(line)
...
This text will be escaped by \"my_escaper\"
Does this work?\tYes it does
And can we span
multiple lines?\t\"Yes\twe\tcan!\"

개량:

  • 코드를 함수로 바꿨다
  • 여러 줄 지원 추가
  • 탈출 버그 수정
  • 특정 복수 교체를위한 기능을 쉽게 생성

즐겨! 🙂


답변

문자열 템플릿의 사용법을 제안하고 싶습니다. 문자열을 사전에 대치하면 모든 것이 설정됩니다! docs.python.org의

>>> from string import Template
>>> s = Template('$who likes $what')
>>> s.substitute(who='tim', what='kung pao')
'tim likes kung pao'
>>> d = dict(who='tim')
>>> Template('Give $who $100').substitute(d)
Traceback (most recent call last):
[...]
ValueError: Invalid placeholder in string: line 1, col 10
>>> Template('$who likes $what').substitute(d)
Traceback (most recent call last):
[...]
KeyError: 'what'
>>> Template('$who likes $what').safe_substitute(d)
'tim likes $what'