awk / sed / etc concatenando colunas em um arquivo

2

Eu me pergunto o que é uma maneira mais simples de fazer isso:

awk 'NR > 1 {print $1"\t"$2"\t"$3"\t"$4"\t"$5"\t"$6"\t"$7"\t"$8"\t"$9$10$11$12$13$14$15$16}'  file.in > file.out

que é simplesmente falando "concatene as colunas de 9 a 16 removendo as guias entre elas"

As colunas mescladas 9-16 se tornam "Notes", portanto, podem incluir espaços em branco.

A partir de hoje, existem 16 colunas, mas isso pode evoluir em mais / menos, se necessário. Eventualmente, a coluna 9 (9-16 concatenada) torna-se campo "notas".

Felicidades,
Xi

    
por xi100f 28.07.2016 / 17:23

6 respostas

5
paste <(cut -f 1-8 file) <(cut -f9- file | tr -d '\t')
    
por 29.07.2016 / 08:37
3

Assumindo algumas linhas de valores separados por tabulações, gerados desta forma:

% perl -E 'say join "\t", 1..8 for 1..3'

As várias colunas podem ser tratadas conforme necessário por meio das sinalizações adequadas e href="https://metacpan.org/pod/distribution/perl/pod/perlvar.pod"> variáveis e functions disponível em Perl.

% perl -E 'say join "\t", 1..8 for 1..3' \
| perl -pale '$_=join "\t", @F[0..3], join "", @F[4..7] if $. > 1' 
1   2   3   4   5   6   7   8
1   2   3   4   5678
1   2   3   4   5678
% 
    
por 28.07.2016 / 17:43
2

Sim, de muitas maneiras. Eu testei os dois seguintes em um arquivo criado por:

perl -le 'next if $.==1; for(1..20){print join "\t",1..20 }' > file

É um arquivo com 20 linhas e 20 colunas separadas por tabulações.

  1. Perl

    perl -F'\t' -ale '$"="\t";print "@F[0..7]",@F[8..$#F]' file 
    

    Observe que isso une todos os campos do 10º ao fim. Se você quiser apenas participar de 9 a 16, use isto:

    perl -F'\t' -ale '$"="\t"; print "@F[0..7]", @F[8..15], "\t@F[16..$#F]"' file 
    
  2. awk

    awk -F'\t' 'NR>1{
                    for(i=1;i<9;i++){
                        printf "%s\t",$i
                    }
                    for(i=9;i<=NF;i++){
                        printf "%s",$i
                    }print "" 
                }' file 
    

    Como antes, isso unirá todas as colunas após o 10º. Se você quiser apenas participar de 9 a 16, use isto:

    awk -F'\t' 'NR>1{
                    for(i=1;i<9;i++){
                        printf "%s\t",$i
                    }
                    for(i=9;i<=16;i++){
                        printf "%s",$i
                    }
                    for(i=17;i<=NF;i++){
                        printf "\t%s", $i
                    }
                    print ""
                }' file 
    

Concedido, as soluções awk não são muito curtas, mas pelo menos você não precisa especificar todos os campos manualmente.

    
por 28.07.2016 / 17:48
2

Alternativa em Python

$ cat file | python -c "import sys
for line in sys.stdin: l=line.rstrip('\r\n').split('\t'); print('\t'.join(l[:9]) + ''.join(l[9:]))
"

sed alternativa

s/(([^\t]*\t){8})/\n/
h
s/[^\n]*\n//
s/\t//g
G
s/([^\n]*)\n([^\n]*)\n.*//

Exemplo de uso:

$ sed -r "s/(([^\t]*\t){8})/\n/;h;s/[^\n]*\n//;s/\t//g;G;s/([^\n]*)\n([^\n]*)\n.*//" file

Explicação:

Suponha que file seja

a   b   c   d   e   f   g   h   i   j   k   l

O separador em file é a guia.

  1. sed lê a linha atual.

    • o espaço padrão é a b c d e f g h i j k l
  2. s/(([^\t]*\t){8})/\n/ divide a linha em duas partes.

    • o espaço padrão é a b c d e f g h \ni j k l
  3. h armazena espaço de padrão no espaço de espera.

    • o espaço padrão é a b c d e f g h \ni j k l
    • O espaço de retenção
    • é a b c d e f g h \ni j k l
  4. s/[^\n]*\n// remove a primeira parte do espaço padrão.

    • o espaço padrão é i j k l
    • O espaço de retenção
    • é a b c d e f g h \ni j k l
  5. s/\t//g remove as guias no espaço padrão.

    • o espaço padrão é ijkl
    • O espaço de retenção
    • é a b c d e f g h \ni j k l
  6. G acrescenta \n e mantém espaço no espaço padrão.

    • o espaço padrão é ijkl\na b c d e f g h \ni j k l
    • O espaço de retenção
    • é a b c d e f g h \ni j k l
  7. s/([^\n]*)\n([^\n]*)\n.*// divide o espaço do padrão e o substitui pela segunda e primeira partes sem \n .

    • o espaço padrão é a b c d e f g h ijkl
    • O espaço de retenção
    • é a b c d e f g h \ni j k l
  8. sed imprime o espaço do padrão.

É possível modificar o código e remover guias nas colunas do meio:

s/(([^\t]*\t){3})(([^\t]*\t){4})(.*)/\n\n/
h
s/[^\n]*\n([^\n]*)\n.*//
s/\t//g
G
s/([^\n]*)\n([^\n]*)\n([^\n]*)\n(.*)//
    
por 28.07.2016 / 22:38
2

Com o GNU sed (assumindo que os campos são delimitados por tabulações na entrada):

sed 's/\t//9g'

Exclui do 9º ao último caractere de tabulação em cada linha.

Se houver mais de 16 campos na entrada e você não quiser os adicionais:

cut -f 1-16 | sed 's/\t//9g'
    
por 29.07.2016 / 23:07
1

awk:

awk -v OFS="\t" '{for (i=10; i<=NF; i++) $9 = $9 " " $i; NF = 9; print}' file

Os campos 10 até o final são anexados ao campo 9, em seguida, o número de campos é limitado ao primeiro 9 e a linha é impressa usando a tabulação como o separador do campo de saída.

Suponho que você queira que os campos concatenados sejam separados por um espaço.
Caso contrário, altere $9 " " $i para $9 $i

    
por 29.07.2016 / 22:47