$ echo "no" | grep -P '^(?!yes).*'
no
A expressão não é uma expressão regular estendida básica nem padrão, mas uma PCRE, uma "expressão regular compatível com Perl". O GNU grep sabe disso se você usar o utilitário com seu -P flag.
Colocar a expressão entre aspas simples (o que você deve fazer, uma vez que é uma string estática) também impede que bash reconheça o ?!yes como um padrão de expansão de histórico.
Do manual GNU grep :
-P,--perl-regexpInterpret the pattern as a Perl-compatible regular expression (PCRE). This is experimental and
grep -Pmay warn of unimplemented features.
Do manual bash (minha ênfase):
Only backslash (
\) and single quotes can quote the history expansion character, but the history expansion character is also treated as quoted if it immediately precedes the closing double quote in a double-quoted string.