concatena n linhas com sed

5

Recentemente, fiz uma pergunta como ordenar pares de linhas e uma das respostas sugeriu linhas de concatenação com sed , assim:

cat file.txt | sed -n 'N;s/\n//;p' | sort -t";" -k43,43n | perl -F';' -ane '$,=";";print @F[0..13],"\n";print @F[14..$#F]'

que funcionou de forma brilhante, mas agora o meu problema generalizou para classificar n-tupels de linhas, que não consigo descobrir como fazer com sed.

Tudo o que encontrei foi para 2 linhas ou TODAS as linhas, mas preciso de n linhas (em que n é 5 no momento, mas um modo geral seria ótimo).

Pontos de bônus para uma maneira agradável de reescrever a parte perl para acomodar n linhas, mas o problema é realmente sobre a parte sed .

Eu também não estou pendurado em sed especificamente, então se você tiver uma boa solução usando uma ferramenta de linha de comando diferente, por favor poste-a.

Atualização: Exemplo de entrada (n == 3)

a1;b1;c1; 
n1;m1;l1; 
d1;e1;f1;g1
n2;m2;l2;
a2;b2;c2;
d2;e2;f2;g2
    
por fifaltra 16.12.2015 / 08:41

2 respostas

5
sed -e:n -e$\bo -e'N;s/\n/&/4;to' -ebn -e:o -e'y/\n/ /' <in >out

Isso concatenará 5 linhas - ou 1 + 4 linhas - substituindo cada nova linha por um único espaço. No entanto:

paste -d\  - - - - - <in >out

... também funcionaria.

Sua coisa g sort poderia funcionar como:

paste -d\  - - <input   |
sed 's/.*;\(.*\)/;&/' |
sort -t\; -k1,1         |
cut  -d\; -f2-          |
tr \  \n

... o que seria uma maneira bastante geral de fazê-lo, embora dependa de não haver espaços no arquivo de entrada. ele une todas as duas linhas em um espaço, copia o último campo ; split para a cabeça de cada linha, classifica no primeiro campo, depois corta e divide as linhas de volta.

    
por 16.12.2015 / 08:46
1

Com pequenas modificações, você pode usar a solução que publiquei na sua outra pergunta.

Novamente usando o GNU sed e o GNU awk e assumindo uma estrutura homogênea dos dados, use o último elemento como a chave de classificação:

# Separate input into records, here 3 lines each
sed '3~3G' infile |

# Use GNU awk's built-in sort, here index-string-descending
awk '
  BEGIN { PROCINFO["sorted_in"] = "@ind_str_desc" }
  { h[$NF] = $0 }
  END { for(k in h) print h[k] }
' RS= FS='[;\n]+'   

Saída:

n2;m2;l2;
a2;b2;c2;
d2;e2;f2;g2
a1;b1;c1; 
n1;m1;l1; 
d1;e1;f1;g1
    
por 16.12.2015 / 09:56