tr apenas analisa um caractere por vez, por isso não funciona quando você precisa verificar o contexto.
Como as seções são separadas por linhas vazias, o modo de parágrafo de awk se ajusta bem:
awk -vRS= '{gsub(/\n/, ""); print $0 "\n"}' myfile.txt
A configuração RS empty carrega "registros" separados por linhas vazias e, para cada registro, removemos novamente as novas linhas e depois imprimimos o registro com uma nova linha extra.
Similarmente em Perl, embora com duas novas linhas extras aqui, porque o Perl carrega a nova linha final como qualquer outro caractere:
perl -00ne 's/\n//g; print "$_\n\n"' myfile.txt
Ambos irão tratar várias linhas em branco da mesma forma que uma.
Poderíamos fazer isso com sed, mas é um pouco mais peludo do que minha tentativa original, se precisarmos suportar blocos de mais de duas linhas.
sed -n 'H; $bL; /./d; :L; x; s/\n//g; s/$/\n/; p;' myfile.txt
Anexe a linha atual ao buffer de retenção ( H ) e, em seguida, verifique se essa é a última linha ( $ ), nesse caso, ramifique para L ( bL ). Caso contrário, verifique se há algum caractere ( /./ ) e, em caso afirmativo, exclua ( d ) a linha e volte a iniciar.
Caso contrário (a linha está vazia), passe para L , onde trocamos ( x ) o buffer de espera e a linha atual (espaço padrão), removemos novas linhas ( s/\n//g ), adicionamos outro ao end ( s/$/\n/ ) e imprime implicitamente o espaço do padrão, agora contendo as linhas que coletamos desde a linha em branco anterior. Aqui, linhas extras em branco produzirão mais linhas em branco extras.