copie e substitua a coluna usando unix [duplicate]

4

Eu quero copiar uma primeira coluna de um arquivo (.txt) e substituí-la pela primeira coluna do segundo arquivo em texto delimitado usando o código Unix.

formato de arquivo de entrada arquivo 1

01/01/2007
02/01/2007
03/01/2007
04/01/2007

arquivo 2

20070101 10.2317  79.1638   6.0  26.7  20.9   0.8  14.0  98.6
20070102 10.2317  79.1638   5.6  26.5  20.8   1.9  13.6  98.0
20070103 10.2317  79.1638   7.5  27.7  20.8   0.1  15.8  96.4
20070104 10.2317  79.1638   8.1  26.0  19.6   0.0  15.5  94.1

saída necessária

01/01/2007  10.2317   79.1638   6.0  26.7  20.9   0.8  14.0  98.6
02/01/2007  10.2317   79.1638   5.6  26.5  20.8   1.9  13.6  98.0
03/01/2007  10.2317   79.1638   7.5  27.7  20.8   0.1  15.8  96.4
04/01/2007  10.2317   79.1638   8.1  26.0  19.6   0.0  15.5  94.1
    
por user211078 18.01.2017 / 10:49

3 respostas

3

$ cut -d' ' -f 2- file2 | paste file1 -

O cut removerá a primeira coluna de file2 ( -f 2- significa "campos de saída (colunas) 2 somente em diante"). O resultado disso será passado para paste , que colocará o conteúdo de file1 na primeira coluna. O - no comando paste é um espaço reservado para o que é entregue na entrada padrão (o canal de cut neste caso).

Passo a passo:

$ cut -d' ' -f 2- file2
10.2317  79.1638   6.0  26.7  20.9   0.8  14.0  98.6
10.2317  79.1638   5.6  26.5  20.8   1.9  13.6  98.0
10.2317  79.1638   7.5  27.7  20.8   0.1  15.8  96.4
10.2317  79.1638   8.1  26.0  19.6   0.0  15.5  94.1

$ cut -d' ' -f 2- file2 | paste file1 -
01/01/2007      10.2317  79.1638   6.0  26.7  20.9   0.8  14.0  98.6
02/01/2007      10.2317  79.1638   5.6  26.5  20.8   1.9  13.6  98.0
03/01/2007      10.2317  79.1638   7.5  27.7  20.8   0.1  15.8  96.4
04/01/2007      10.2317  79.1638   8.1  26.0  19.6   0.0  15.5  94.1

O comando cut está esperando uma entrada delimitada por tabulação, mas, como copiei e colei da sua pergunta, ela é delimitada por espaço. Se os dados originais forem, na verdade, delimitados por tabulações, remova o comando -d' ' do comando cut .

O comando paste adicionará uma tabulação entre as colunas 1 e 2 por padrão. Se você quiser um espaço, use paste -d' ' file1 - .

Em outra pergunta , foi perguntado como usar a data já existente em file2 aqui e acabar com o primeiro arquivo completamente.

Acabei com

$ paste <( date -f <( cut -d ' ' -f 1 file2 ) +"%d/%m/%Y" ) \
        <( cut -d ' ' -f 2- file2 )
01/01/2007      10.2317  79.1638   6.0  26.7  20.9   0.8  14.0  98.6
02/01/2007      10.2317  79.1638   5.6  26.5  20.8   1.9  13.6  98.0
03/01/2007      10.2317  79.1638   7.5  27.7  20.8   0.1  15.8  96.4
04/01/2007      10.2317  79.1638   8.1  26.0  19.6   0.0  15.5  94.1

Note que isso requer um shell que entenda a substituição do processo ( <( ... ) ), como bash ou ksh , e também requer a implementação do date do GNU.

Um pouco de explicação pode estar em ordem:

A substituição do processo <( ... ) mais ou menos cria um arquivo temporário contendo a saída do comando dentro dos parênteses (na verdade, um FIFO em /dev/fd ). Então, todo o comando passará por duas etapas de substituição:

paste <( date -f output_of_cut1 +"%d/%m/%Y" ) \
      output_from_cut2

date -f filename lerá as datas no arquivo filename e formatará cada uma delas de acordo com a string de formato indicada.

Então:

paste output_from_date output_from_cut2

que colará as colunas com a saída de date como a primeira coluna e a saída do segundo cut como as outras colunas.

    
por 18.01.2017 / 11:08
1

Dependendo da versão awk , você pode transformar a primeira coluna com:

awk '{$1=substr($0,7,2)"/"substr($0,5,2)"/"substr($0,1,4); print $0}'  FILE2.csv

exemplo:

echo "20070101 10.2317  79.1638   6.0  26.7  20.9   0.8  14.0  98.6"  | awk '{$1=substr($0,7,2)"/"substr($0,5,2)"/"substr($0,1,4); print $0}'

retorna:

 01/01/2007 10.2317 79.1638 6.0 26.7 20.9 0.8 14.0 98.6

Notas:

Primeira parte redefine o valor das primeiras colunas

 $1=substr($0,7,2)"/"substr($0,5,2)"/"substr($0,1,4)

e print $0 imprimem linha inteira com a primeira coluna redefinida

    
por 18.01.2017 / 11:11
1

Você pode usar o awk para isso:

awk 'NR==FNR{a[++i]=$1;next}{$1=a[++k]; print}' file1 file2

NR==FNR é um significado de padrão: {a[++i]=$1;next} é executado em cada registro (ou seja, linha) no arquivo1.

a[++i]=$1;next significa: salvar o primeiro campo do registro (isto é, linha) na matriz com o índice do número do registro (isto é, o número da linha do arquivo1), depois ler no próximo registro

$1=a[++k]; print significa: copiar o conteúdo da matriz com indx k para o primeiro campo do registro atual (isto é, linha) (que é sempre o k-ésimo registro (isto é, linha)) arquivo2).

    
por 18.01.2017 / 11:24