Most of the time, you can avoid variable length lookbehinds by using \K.
s/(?<=foo.*)bar/moo/s;
would be
s/foo.*\Kbar/moo/s;
Anything up to the last \K encountered is not considered part of the match (e.g. for the purposes of replacement, $&, etc)
Negative lookbehinds are a little trickier.
s/(?<!foo.*)bar/moo/s;
would be
s/^(?:(?!foo).)*\Kbar/moo/s;
because (?:(?!STRING).)* is to STRING as [^CHAR]* is to CHAR.
If you’re just matching, you might not even need the \K.
/foo.*bar/s
/^(?:(?!foo).)*bar/s