Como dividir uma enorme linha de caracteres em várias linhas com números iguais de colunas?

1

Se um arquivo de dados se parece com:

snp200 snp1 snp100 snp32 1 1 0 2 0 0 0 2 2 2 2 1...

como posso quebrar a linha quando snp .. terminar e usá-los como nomes de colunas e depois dividir o resto dos dígitos igualmente (o número total de dígitos em cada linha deve ser igual ao número de nomes de coluna na primeira linha) e coloque-os em linhas subseqüentes como cada um. neste pequeno exemplo existem 4 nomes de colunas e assim o resto das linhas tem 4 deve ter 4 dígitos saída:

snp200 snp1 snp100 snp32
1 1 0 2
0 0 0 2
2 2 2 1 
...

qualquer sugestão considerando que os dados reais são de fato enormes (mais de 32.000 nomes de colunas)

    
por zara 06.10.2016 / 04:25

5 respostas

3

Uma opção é usar um perl regex , assim:

cat in.txt | perl -pe 's/(([^ ]+ +){4})/$1\n/g' > out.txt

A expressão regular disse para encontrar um ou mais espaços não seguidos por um ou mais espaços e agrupar os dois itens anteriores em um conjunto de quatro e depois adicionar uma nova linha após cada partida.

Caso de teste:

echo "snp200 snp1 snp100 snp32 1 13454356 0 2 0 0 0 2 2 2 2 1" | perl -pe 's/(([^ ]+ +){4})/$1\n/g'
snp200 snp1 snp100 snp32 
1 13454356 0 2 
0 0 0 2 
2 2 2 1
    
por 06.10.2016 / 04:47
2

Usando o rs(1) do BSD:

rs 0 4 <data.txt >out.txt
    
por 06.10.2016 / 09:48
1

Se tudo o que você precisa é de quatro colunas:

$ cat data.file | tr ' ' '\n' | columns -w 10 -c 4

snp200    snp1      snp100    snp32
1         1         0         2
0         0         0         2
2         2         2         1
    
por 06.10.2016 / 16:03
1

com zsh :

$ print -raC4 snp200 snp1 snp100 snp32 1 1 0 2 0 0 0 2 2 2 2 1...
snp200  snp1    snp100  snp32
1       1       0       2
0       0       0       2
2       2       2       1...

POSIXly:

$ printf '%-7s %-7s %-7s %-7s\n' snp200 snp1 snp100 snp32 1 1 0 2 0 0 0 2 2 2 2 1...
snp200  snp1    snp100  snp32
1       1       0       2
0       0       0       2
2       2       2       1...

Ou se os dados estiverem em um arquivo, com tr + paste :

tr -s ' ' '\n' < file | paste - - - -
    
por 06.10.2016 / 16:43
1

Se o número de rótulos nomeados puder variar, é melhor contabilizá-los primeiro. Em Perl, algo assim:

perl -lane '
   $n++ while $F[$n] =~ /^[a-z]/; 
   do { 
     print join(" ", @F[$_*$n .. $_*$n + $n - 1])
   } while (++$_*$n <= $#F)' < input

Primeiro, aumente $n para cada campo que comece com uma letra, indicando o número de campos nomeados, depois imprima repetidamente, unidos por espaços, campos 0*$n a 1*$n - 1 e, em seguida, 1*$n to 2*$n - 1 etc. contanto que $n vezes o contador seja menor que o número total de campos na linha. Isso pressupõe que todos os dados estão em uma única linha, linhas subseqüentes serão tomadas como conjuntos de dados separados.

    
por 06.10.2016 / 17:34