Like the other answers, I’d use a positive lookahead assertion.
Then to fix the issue raised by Rawing in a couple of the comments (what about words like “beard”?), I’d add (\b|$). This matches a word boundary or the end of the string, so you only match on the word bear, and nothing longer.
So you get the following:
import re
def bear_replace(string):
return re.sub(r"\w+ (?=bear(\b|$))", "the ", string)
and test cases (using pytest):
import pytest
@pytest.mark.parametrize('string, expected', [
("perfect bear swims", "the bear swims"),
# We only capture the first word before 'bear
("before perfect bear swims", "before the bear swims"),
# 'beard' isn't captured
("a perfect beard", "a perfect beard"),
# We handle the case where 'bear' is the end of the string
("perfect bear", "the bear"),
# 'bear' is followed by a non-space punctuation character
("perfect bear-string", "the bear-string"),
])
def test_bear_replace(string, expected):
assert bear_replace(string) == expected