Usando ^
fora dos parênteses [...]
que significa início da linha. E você cometerá erros quando houver um ponto de escape entre colchetes, [^\.]
significa qualquer coisa, exceto barra invertida \
e ponto .
, não apenas ponto .
Outra observação de que abcd[^.]
não corresponderá a abcd no final da linha.
Então você precisa:
$ grep -E 'abcd([^.]|$)' <file
abcd
defgh. abcd
abcd .defgh