Perché ti stupisce? grep matcha sottostringhe che iniziano o finiscono in un punto qualunque della riga, di fatto la tua espressione richiede semplicemente che ci siano più di tre p di fila in un punto qualunque di ciascuna riga (e quindi non pone limite al numero massimo di p consecutive). Per fare quello che chiedi, dovresti usare una regex del tipo
(a te il capire come funzionacodice:(^|[^p])p{3,5}([^p]|$))

)
Rispondi quotando
) avevo fatto un po' di confusione a mia volta
) e di grep.
