Ograniczanie zachłanności w wyrażeniach regularnych w Pythonie

Wyrażenia regularne domyślnie są zachłanne. Oznacza to, że przechwytują maksymalną możliwą liczbę znaków. Przeanalizujmy to na przykładzie. Załóżmy, że mamy taki ciąg znaków:

pythontxt = 'aeeex zzz x kkk'

W tym ciągu chcemy znaleźć podciąg 'aeeex' według następującego wzorca: litera 'a', następnie dowolny znak jeden lub więcej razy, następnie litera 'x':

pythonres = re.sub('a.+x', '!', txt)
print(res)

Chociaż oczekujemy otrzymania ciągu '! zzz x kkk', wypisany zostanie ciąg '! kkk'. Chodzi o to, że nasze wyrażenie regularne szuka wszystkich znaków od litery 'a' do litery 'x'. Ale w naszym ciągu są dwie litery 'x'! Z powodu zachłanności okazuje się, że wyrażenie regularne szuka do ostatniego 'x', tym samym przechwytując nie to, czego potrzebowaliśmy.

Oczywiście często takie zachowanie jest właśnie tym, czego potrzebujemy. Ale konkretnie w tym przypadku należy wyłączyć zachłanność i nakazać wyrażeniu regularnemu, żeby szukało do pierwszego 'x'. W tym przypadku należy po operatorze powtórzenia postawić znak zapytania:

pythonres = re.sub('a.+?x', '!', txt)
print(res) # wypisze ciąg '! zzz x kkk'

Zachłanność można ograniczać wszystkim operatorom powtórzenia: i *, i ?, i {} - o tak: *?, ?? i {}?.

Задание 1

Dany jest ciąg:

pythontxt = 'aba accca azzza wwwwa'

Napisz wyrażenie regularne, które znajdzie wszystkie ciągi, na których brzegach znajdują się litery 'a', i zastąpi każdy z nich '!'. Między literami 'a' może znajdować się dowolny znak (oprócz 'a').