Classificando blocos de linhas

12

Eu tenho um arquivo que contém 4 linhas. Aqui está um trecho dele contendo 8 linhas

6115 8.88443
6116 6.61875
6118 16.5949
6117 19.4129
6116 6.619 
6117 16.5979 
6118 19.4111
6115 8.88433  

O que eu quero fazer é classificar um bloco, onde cada bloco consiste em 4 linhas com base na primeira coluna. A saída para o trecho deve ter a aparência mostrada abaixo.

6115 8.88443
6116 6.61875
6117 19.4129
6118 16.5949
6115 8.88433 
6116 6.619 
6117 16.5979 
6118 19.4111 
    
por Meenakshi 09.11.2013 / 17:29

6 respostas

16

Uma opção é usar para adicionar um prefixo de número de série inicial cada N linhas (N = 4 no seu caso). Em seguida, alimente o prefixo como a coluna de classificação principal em sort .

Exemplo com N = 4:

awk '{print int((NR-1)/4), $0}' file.txt | sort -n -k1,1 -k2,2 | cut -f2- -d' '
    
por 09.11.2013 / 17:50
7

Se este é um fora e você não quer aprender python, perl ou awk, você pode usar os comandos básicos split e sort .

Primeiro, divida o arquivo em blocos de 4 linhas com a opção -l :

split -a 6 -l 4 input_file my_prefix_
for fn in my_prefix_*; do
    sort -n -o $fn $fn
done
cat my_prefix_* > output_file
rm my_prefix_*

O sort -n classifica por valor numérico da primeira coluna (999 antes de 1234). -a 6 deve cuidar de um arquivo com 26 ^ 6 * 4 linhas. my_prefix_ deve ser algo exclusivo para o diretório com o qual você trabalha.

    
por 09.11.2013 / 17:58
3

Você pode fazer isso com o Perl:

perl -nle '
   push @a,$_;
   unless($. % 4){
       print join "\n",sort {$a <=> $b} @a; # Sort @a, and print its contents
       @a = (); # Empty @a to start a new block
   }
' your_file

Como isso funciona

  • -n - > execute o código para cada linha de entrada (e coloque a linha atual em $_ )
  • -l - > Anexe uma nova linha à saída de qualquer print
  • -e - > execute a seguinte string como código Perl
  • Cada linha é anexada à matriz @a .
  • $. contém o número da linha atual e, a menos que esse número não seja congruente com zero, o módulo 4 continuará trabalhando. Se é congruente a zero módulo 4, atingimos uma linha cujo número é um múltiplo de 4 (o fim de um bloco), nesse caso, classificamos as entradas em @a em ordem crescente ordem numérica e imprima as entradas na matriz classificada, unidas por uma nova linha à saída padrão.
por 09.11.2013 / 17:43
2

Usando um shell parecido com o Bourne,

while read a ; do                                           # Try reading a line.
    read b ; read c ; read d                                # OK, read 3 more.
    printf '%s\n%s\n%s\n%s\n' "$a" "$b" "$c" "$d" | sort -n # Sort them.
done < data
    
por 10.11.2013 / 06:23
2

Aqui estão algumas soluções "%"awk "puras":

Se os índices forem sempre a mesma sequência inteira de incremento (6115-6119), como em seus dados de amostra, você pode usar um "atalho" algorítmico:

awk '{a[$1]=$0} !(NR%4){for(i=6115;i<6119;print a[i++]);}'

Isso faz

  • Adicione todas as linhas à matriz a , distribuídas nas posições de índice 6115-6119
  • Em cada quarta linha ( !(NR%4) ), percorra o conteúdo da matriz para imprimir na ordem desejada.

Se os seus índices numéricos são sempre os mesmos, mas não uma sequência inteira de incrementos, você terá que ordenar:

awk '{a[$1]=$0} !(NR%4){asort(a,b); for(i=1;i<5;print b[i++]);}'

Nota: Isso é com o GNU awk, outros podem não suportar asort .

Se cada bloco de quatro puder ter IDs numéricos diferentes:

awk '{a[$1]=$0} !(NR%4){asort(a); for(i=1;i<5;print a[i++]); delete a}'

Nota: TIL de auto-resposta @Gilles (+2) esse uso de delete não é (ainda) POSIX, mas universalmente suportado .

Uma versão com o uso correto de delete :

awk '{a[$1]=$0} !(NR%4){asort(a); for(i=1;i<5;delete a[i++]){print a[i]}}'

Uma versão sem exclusão, usando mais memória e dimensões:

awk '{a[n][$1]=$0} !(NR%4){asort(a[n]); for(i=1;i<5;print a[n][i++]); n++}
    
por 04.05.2017 / 20:31
1

Você pode obter uma solução limpa com R. Se a tabela acima estiver em um arquivo chamado "table.txt", execute as etapas a seguir. O resultado desejado estará no arquivo "tableout.txt".

> x = read.table("table.txt", col.names=c("a", "b"))
> x
     a        b
1 6115  8.88443
2 6116  6.61875
3 6118 16.59490
4 6117 19.41290
5 6116  6.61900
6 6117 16.59790
7 6118 19.41110
8 6115  8.88433
> x["index"] = c(rep(1, 4), rep(2, 4))
> x
     a        b index
1 6115  8.88443     1
2 6116  6.61875     1
3 6118 16.59490     1
4 6117 19.41290     1
5 6116  6.61900     2
6 6117 16.59790     2
7 6118 19.41110     2
8 6115  8.88433     2     
> xord = x[with(x, order(index, a)), ]
> xord
     a        b index
1 6115  8.88443     1
2 6116  6.61875     1
4 6117 19.41290     1
3 6118 16.59490     1
8 6115  8.88433     2
5 6116  6.61900     2
6 6117 16.59790     2
7 6118 19.41110     2
> write.table(xord[,1:2], "tableout.txt", row.names=FALSE, col.names=FALSE)

Veja também Como classificar um dataframe por coluna (s) em R .

    
por 09.11.2013 / 22:58