awk -v RS= -v cmd=sort '{print | cmd; close(cmd); print ""}' file
Definir o separador de registros RScomo uma sequência vazia faz com que awk avance nos parágrafos de cada vez. Para cada parágrafo, canalize o parágrafo (in $0) para cmd (que está definido como sort) e imprima a saída. Imprima uma linha em branco para separar os parágrafos de saída com a print "".
Se estamos dando exemplos de perl, apresento uma abordagem alternativa à de Stephane:
perl -e 'undef $/; print join "\n", sort (split /\n/), "\n"
foreach(split(/\n\n/, <>))' < file
Desative o separador de campos ( undef $/), isso nos permite usar <>e obter todo o STDIN. Nós, então, splitpor aí \n\n(parágrafos). foreach"paragraph", sortas linhas splittocando novas linhas, introduzindo- sortas e joinjuntando-as novamente e seguindo uma trilha \n.
No entanto, isso tem um efeito colateral de adicionar um separador "parágrafo final" no último parágrafo (se ele não tivesse um antes). Você pode contornar isso com o pouco menos bonito:
perl -e 'undef $/; print join "\n", sort (split /\n/) , (\$_ == \$list[-1] ? "" : "\n")
foreach(@list = split(/\n\n/, <>))' < file
Isso atribui os parágrafos a @liste, em seguida, há uma "operação ternária" para verificar se é o último elemento da foreach(a \$_ == \$list[-1]verificação). imprima ""se for ( ? ...), else ( : ...) imprima "\n"para todos os outros "parágrafos" (elementos de @list).
awksolução que evita asortsobrecarga! Sorrateiro!