次のようなテキストがあります。
Added "a-foo-b" foo.
目標は、正規表現を使用して 2 番目の foo を bar に置き換え、最初の foo を 2 つの二重引用符で囲んだままにすることです。したがって、上記のテキストで、私が探している結果は次のとおりです。
Added "a-foo-b" bar.
ありがとう
次のようなテキストがあります。
Added "a-foo-b" foo.
目標は、正規表現を使用して 2 番目の foo を bar に置き換え、最初の foo を 2 つの二重引用符で囲んだままにすることです。したがって、上記のテキストで、私が探している結果は次のとおりです。
Added "a-foo-b" bar.
ありがとう
import re
pat = re.compile(r'("[^"]+".*)foo')
s = '''Added "a-foo-b" foo.'''
s_new = re.sub(pat, r'\1bar', s)
print(s_new)
目標は二重引用符をそのままにしておくことだとおっしゃっていたので、私は二重引用符をキーとして集中しました。括弧は、一致した文字列を保存する「一致グループ」を形成します。この一致グループは、二重引用符とその中にあるものに一致し、パターンは 2 番目の foo に一致します。置換パターンは、一致したすべてのものを置換しますが、 a を使用し\1
て一致グループ部分を元に戻し、bar
その 2 番目の を置換する必要があるため、問題ありませんfoo
。
foo
置き換えたいの後にこれ以上二重引用符を付けられないことがわかっている場合は、次のパターンの方が適している可能性があります。
pat = re.compile(r'(".*".*)foo')
このパターンは、二重引用符、任意の文字列、別の二重引用符の順に一致します。引用符で囲まれた文字列にエスケープされた二重引用符が含まれている場合、最初のパターンは機能しませんが、これは機能します。ただし、この文字列でこのパターンを使用すると、次のようになります。
s = '''Added "a-foo-b" foo. "Wow, another foo"'''
一致グループは、引用符で囲まれていても、2 番目の foo を超えて一致し、3 番目の foo に一致します。これは、パターン マッチが「貪欲」であるためです。
編集:
質問: ええ、もしもs = '''Added "a-foo-b" foo.Deleted "a-foo-b".'''
回答: パターンが常に成り立つ場合、二重引用符内にエスケープされた二重引用符が存在しないことがわかり、最初のパターンを使用できます。次に、複数のパターンを適用して、必要なものを検出および/または置換できます。 pat_added
以下は、以前に解決したかった問題を解決します。文字列の一部に固定されるAdded
ため、文字列の一部には何もしませんDeleted
。引用符内の文字列の一部を照合して置換したい場合は、そのpat_deleted
方法を示します。3 つの一致グループがあり、最初と最後のグループを元に戻して、中間のグループを置き換えることができます。実際には、中間の一致グループは必要ありません。最初のパターンで行ったように、置換する部分を一致グループの外に残すことができます。
import re
pat_added = re.compile(r'(Added\s+"[^"]+"\s+)\w+')
pat_deleted = re.compile(r'(Deleted\s+"[a-z]-)([^-]+)(-[a-z]"\.)')
s = '''Added "a-foo-b" foo.Deleted "a-foo-b".'''
s = re.sub(pat_added, r'\1bar', s)
s = re.sub(pat_deleted, r'\1bar\3', s)
print(s)
テキストが常にドットで終わる場合は、次のようなことを試すことができます。
echo 'Added "a-foo-b" foo.' | sed s/foo\.$/bar/g
Added "a-foo-b" bar
文字列メソッドによるアプローチ。
>>> s='Added "a-foo-b" foo test'
>>> needle='foo'
>>> rind=s.rfind('foo')
>>> if rind!=-1:
... s=s[:rind] + needle + s[rind+len(needle):]