# Позитивный и негативный просмотр в регулярках Python

Иногда нужно решить задачу такого типа: найти строку `'aaa'` и заменить ее на `'!'`, но только если после `'aaa'` стоит `'x'`, а сам `'x'` при этом не заменять. Если мы попытаемся решить задачу `'в лоб'`, то у нас ничего не выйдет:

`txt = 'aaax baaa' res = re.sub('aaax', '!', txt) print(res) # выведет '! baaa', а хотели '!x baaa'`

## Просмотр вперед

Для решения задачи нужен способ сказать, что `'x'` не следует заменять. Делается это с помощью специальных скобок `(?= )`, которые просто смотрят, но не забирают с собой.

Эти скобки называются позитивный просмотр вперед. Позитивный - так как `'x'` (в нашем случае) должен быть - только тогда произойдет замена.

Давайте применим эти скобки для решения нашей задачи:

`txt = 'aaax baaa' res = re.sub('aaa(?=x)', '!', txt) print(res) # выведет '!x aaab`

Есть и негативный просмотр вперед - `(?! )` - он, наоборот, говорит, что чего-то должно не быть. В следующем примере, замена произойдет, только если после `'aaa'` стоит НЕ `'x'`:

`txt = 'aaax aaab' res = re.sub('aaa(?!x)', '!', txt) print(res) # выведет 'aaax !b'`

## Просмотр назад

Аналогичным образом есть позитивный просмотр назад - `(?<= )`. В следующем примере замена произойдет, только если перед `'aaa'` стоит `'x'`:

`txt = 'xaaa' res = re.sub('(?<=x)aaa', '!', txt) print(res) # выведет 'x!'`

И есть также негативный просмотр назад - `(?<! )`. В следующем примере замена произойдет, только если перед `'aaa'` не стоит `'x'`:

`txt = 'baaa' res = re.sub('(?<!x)aaa', '!', txt) print(res) # выведет 'b!'`

## Практические задачи

Дана строка, содержащая имена функций:

`txt = 'func1() func2() func3()'`

Получите массив имен функций из строки.

Дана строка с тегом:

`txt = '<a href="" class="eee" id="zzz">'`

Получите массив имен атрибутов этого тега.

Дана строка с переменными:

`txt = '$aaa $bbb $ccc xxxx'`

Получите подстроки, перед которыми стоит символ доллара.

← →
↑