tail -3
não imprime mais de 3 linhas; imprime 3 ou menos. Então, se 'grep' encontrar 3 ou menos linhas correspondentes, tail irá passar TODAS para a stdout. Se houver mais de três correspondências, tail
as limitará a apenas três linhas.
Você resolveu seu problema antes mesmo de postá-lo aqui, pois seu comando faz exatamente o que você precisa ...
Isso é o que acontece quando você está trabalhando à noite:)
EDIT: Eu provavelmente interpretei mal o seu problema ..
Se você quiser imprimir o ARQUIVO INTEIRO quando os <3 fósforos forem encontrados - basta executar
f="testfile.c" && C=3 && [ $(grep -c "#include" ${f}) -lt ${C} ] && cat ${f} || grep "#include" ${f} |tail -${C}
No entanto, se você estiver trabalhando em um FS possivelmente lento (por exemplo, NFS) ou se estiver lidando com arquivos com MUITAS linhas ou linhas extremamente longas, isso pode ser muito lento para você, já que você precisa ler o arquivo duas vezes ..
f="testfile.c" && C=3 && CONTENT=$(cat "${f}") && MATCHES=$(echo "$CONTENT"|grep "#include"|tail -${C}) && [ $(echo "$MATCHES" | wc -l) -lt ${C} ] && echo "$CONTENT" || echo "$MATCHES"
Desta forma, você terá que abrir e ler o arquivo apenas uma vez, MAS você o colocará em buffer na RAM (que é muito mais rápido que os dispositivos de armazenamento). Se você estiver com pouca memória RAM ou fazendo o buffer do arquivo, isso é muito caro para você, use o primeiro comando [onde o arquivo é aberto duas vezes]; é mais lento, mas não trava o sistema operacional ou o aplicativo (embora o risco de ficar preso no estado 'D' seja maior ... e também não é bom para o sistema operacional.)