(?! ) はマッチした部分の“後続文字列”の指示、なので、
たとえば $str =~ / hoge(?!fuga) /x と指定すると
hogehoge にはマッチするが hogefuga にはマッチしない。

ということのようだ。

条件式も併用してたとえば
$str =~ / (.*)hoge /x and $1 !~ /fuga/
みたいにしないとだめっぽいが。
あとは識者待ち。