repita uma linha, dividindo um campo

2

Eu tenho um arquivo delimitado por tabulação no qual, em cada linha, eu tenho isto:

K00001;K00004;K00008    0   0   34  0   0   0   0   0   0   0   0   0   0   0   0   0   36  0   0   52  0   0   0   6   0

Eu gostaria de ter uma linha com um código único e a mesma sequência de números como esta:

K00001 0    0   34  0   0   0   0   0   0   0   0   0   0   0   0   0   36  0   0   52  0   0   0   6   0    
K00004 0    0   34  0   0   0   0   0   0   0   0   0   0   0   0   0   36  0   0   52  0   0   0   6   0    
K00008 0    0   34  0   0   0   0   0   0   0   0   0   0   0   0   0   36  0   0   52  0   0   0   6   0
    
por Ilario Ferrocino 08.12.2014 / 15:50

7 respostas

6

Você pode usar o awk para dividir a primeira coluna:

~$ awk '{split($1,a,";"); $1="";for (i in a){print a[i],$0}}' myfile
K00001  0 0 34 0 0 0 0 0 0 0 0 0 0 0 0 0 36 0 0 52 0 0 0 6 0
K00004  0 0 34 0 0 0 0 0 0 0 0 0 0 0 0 0 36 0 0 52 0 0 0 6 0
K00008  0 0 34 0 0 0 0 0 0 0 0 0 0 0 0 0 36 0 0 52 0 0 0 6 0

Você divide a primeira coluna em ; ( split($1,a,";") ) e depois a exclui para imprimir toda a (nova) linha ( $0 ) para cada item da matriz.

Como sugerido no comentário, após a edição, podemos ver que as guias são usadas como separador. Para usar a guia como separador de campo de saída, você pode usar OFS="\t" , por exemplo, na BEGIN parte do awk. Além disso, um campo vazio é inserido com $1="" . Portanto, em vez de imprimir a[i] , em seguida, $0 , é melhor definir $1 para a[i] e, em seguida, imprimir $0 :

~$ awk 'BEGIN{OFS="\t"}{split($1,a,";"); for (i in a){$1=a[i];print}}' myfile
K00001  0       0       34      0       0       0       0       0       0       0       0       0       0       0       0       0       36      0       0       52      0       0       0       6       0
K00004  0       0       34      0       0       0       0       0       0       0       0       0       0       0       0       0       36      0       0       52      0       0       0       6       0
K00008  0       0       34      0       0       0       0       0       0       0       0       0       0       0       0       0       36      0       0       52      0       0       0       6       0
    
por 08.12.2014 / 16:03
3

com sed :

sed 's/^\([^[:blank:];]*\);\([^[:blank:]]*\)\(.*\)/\
/;P;D'
    
por 08.12.2014 / 16:55
3

Isso deve fazer o que você quiser. Basicamente, colocamos o primeiro campo (as chaves) em $k e o restante dos campos em $f dividindo em \t e limitando a divisão aos primeiros 2 campos. Em seguida, dividimos as chaves em ; e imprimimos cada tecla junto com os campos restantes em sua própria linha.

perl -nle '($k, $f) = split "\t", $_, 2; print "$_\t$f" for split ";", $k'

-n faz um loop sobre a entrada. Você pode enviar seu arquivo para perl ou passar o nome do arquivo de entrada no final da linha de comando. -l ativa o gerenciamento automático de término de linha.

    
por 08.12.2014 / 16:08
2

o arquivo awk

 {
   split($1,A,";") ;
   for ( a in A )
    {
    printf "%s",A[a] ;
    for(i=2;i<=NF;i++) printf "\t%s",$i ;
    printf "\n" ;
    }
  }

onde

  • split($1,A,";") colocado em A todo o sub arquivado de $ 1
  • for ( a in A ) loop através do valor de A
  • printf "%s",A[a] ; imprime o primeiro valor
  • for(i=2;i<=NF;i++) printf "\t%s",$i ; imprime o valor restante na linha de comando
  • printf "\n" ; da nova linha
por 08.12.2014 / 16:00
1

Outro perl one-liner.

$ perl -pe 's/^([^;]+);([^;]+);(\S+)\s+(.*)/$1 $4\n$2 $4\n$3 $4/' file
K00001 0   0   34  0   0   0   0   0   0   0   0   0   0   0   0   0   36  0   0   52  0   0   0   6   0
K00004 0   0   34  0   0   0   0   0   0   0   0   0   0   0   0   0   36  0   0   52  0   0   0   6   0
K00008 0   0   34  0   0   0   0   0   0   0   0   0   0   0   0   0   36  0   0   52  0   0   0   6   0

Outro sed-one liner.

$ sed 's/^\([^;]\+\);\([^;]\+\);\([^ ]\+\) \+\(.*\)/ \n \n /' file
K00001 0   0   34  0   0   0   0   0   0   0   0   0   0   0   0   0   36  0   0   52  0   0   0   6   0
K00004 0   0   34  0   0   0   0   0   0   0   0   0   0   0   0   0   36  0   0   52  0   0   0   6   0
K00008 0   0   34  0   0   0   0   0   0   0   0   0   0   0   0   0   36  0   0   52  0   0   0   6   0
    
por 08.12.2014 / 17:39
0

Versão Perl mais longa, que permite acessar os dados por chave e processar, se necessário. Isso também não usa a captura de expressões regulares.

#!/usr/bin/perl
use warnings; 
use strict;

my %hash; 

while ( my $line = <> ){
    #splitting the line into two parts at the first TAB.
    my ($keys, $value) = split (/\t/ , $line, 2);

    #splits the set of keys at each semicolon
    my @key = split /;/, $keys;

    #@key is used in scalar context here to get the number of keys.
    #this is used to determine how many values we need to put into the hash
    @hash{@key} = ($value) x @key; 
}

for my $key (keys %hash){
    print "$hash{$key}\n"; 
}

Leitura adicional:

por 08.12.2014 / 23:42
0

Dia lento no trabalho, então aqui está uma python solution

python3 -c 'import sys
x = (l.partition("\t") for l in sys.stdin)
x = ((l[0].split(";"), l[1] + l[2]) for l in x)
for a in x:
  print(*a[0], sep=a[1], end=a[1])
' <file
    
por 09.12.2014 / 18:37