unix: substitua uma coluna inteira em um arquivo por um único valor de outro arquivo

2

Eu quero substituir uma coluna em um arquivo por um único valor de outro arquivo usando o unix.

O arquivo 1 é um arquivo pdb, estruturado assim:

HETATM   14  H4B FAD B 600      95.544  50.240  71.308  1.00 -1.00 H  
HETATM   14  H4B FAD B 600      95.544  50.240  71.308  1.00 -1.00 H  

Eu quero substituir o número da coluna 11 por um valor único que é armazenado em outro arquivo (Arquivo 2) que se parece com isto:

[1, 27, -81.883, 4.0]
[3, 38, -66.122, 12.0]
[3, 57, -62.134, 12.0]

Eu quero que o valor do Arquivo 2 (coluna 3 da linha 1) seja o da coluna 11 do Arquivo 1, para que o Arquivo 1 seja assim:

HETATM   14  H4B FAD B 600      95.544  50.240  71.308  1.00 -81.88 H  
HETATM   14  H4B FAD B 600      95.544  50.240  71.308  1.00 -81.88 H

Eu posso substituir a coluna 11 do Arquivo 1 por um único valor (2 neste caso) usando:

awk '{$11=2}1' File1

e eu encontrei código como este de link

awk 'FNR==NR{a[NR]=$3;next}{$2=a[FNR]}1' f2 f1

No entanto, acredito que eu deveria estar usando uma combinação de awk e sed para obter o valor desejado do Arquivo 2 para o Arquivo 1.

O código abaixo me dá a primeira linha da coluna 11:

awk 'FNR==1{print $11}'

Eu simplesmente não consigo descobrir como combinar as duas coisas.

Não consigo pesquisar por valor porque os valores mudam com cada conjunto de dados que eu tenho (centenas de arquivos pdb para modificar).

Alguém pode ajudar?

Ambas as soluções abaixo atrapalham a formatação do meu arquivo pdb, ou seja, eu recebo:

HETATM 1 PA FAD B 600 95.887 47.194 74.387 1.00 -73.248 

em vez de

HETATM    1  PA  FAD B 600      95.987  47.188  74.293  1.00 -73.248

estou fazendo algo errado ou você tem alguma idéia do porquê?

    
por gugy 27.10.2015 / 14:42

3 respostas

2

Primeiro, extraia o campo que você deseja do Arquivo 2:

value="$(awk -F, 'NR==1{print $3;exit}' file2)"

Em seguida, conecte-o ao código de substituição do Arquivo 1:

awk '{$11 = v} 1' v="$value" file1
    
por 27.10.2015 / 15:02
1

Como o valor desejado é a terceira coluna da primeira linha de file2 , você pode obter isso com:

$ awk 'NR==1{print $3}' file2
-81.883,

No entanto, isso também inclui a vírgula que, presumivelmente, você não deseja. Para evitar isso, você pode dizer a awk para usar qualquer espaço ou como delimitadores de campo usando o -F flag:

$ awk -F", " 'NR==1{print $3}' file2
-81.883

O awk permite que você defina uma variável na linha de comando com a opção -v :

   -v var=val
   --assign var=val
          Assign the value val to the variable var,  before  execution  of
          the  program  begins.  Such variable values are available to the
          BEGIN rule of an AWK program.

Assim, você pode executar awk -vfoo="-81.833" {...} e isso tornaria o valor -81.33 disponível como a variável foo no script awk. Se você combinar isso com substituição de comando , você pode passar a saída do primeiro comando awk (o valor desejado) como uma variável (chamada, por exemplo, i ) para um segundo script que substitui o 11º campo pelo valor da variável i :

$ awk -vi="$(awk -F", " 'NR==1{print $3}' file2)" '{$11=i}1;' file1
HETATM 14 H4B FAD B 600 95.544 50.240 71.308 1.00 -81.883 H
HETATM 14 H4B FAD B 600 95.544 50.240 71.308 1.00 -81.883 H
    
por 27.10.2015 / 15:06
0

Eu não entendo muito bem esse problema, mas vou arriscar uma solução, eu acho.

sed -nse'1!{  :out
              1x
              s/  */&\n/10
              s/^/ /p;t
           }
           x; s/..*//;t out
           g; s/[^ ]* *[^ ]* *//
              s/ .*//;p
           x;    :eat
           $d;n;b eat
'  file1 file2 file3 file4 |
sed '      /^ /!{h;d;}
           s///;N;G
           s/\n[^ ]*\(.*\)\n\(.*\)//
'

Isso pode funcionar. Se você tiver um sed que possa manipular -s eparate fluxos de arquivos de entrada, ele deverá alternar entre selecionar apenas o campo desejado do arquivo um e gravar apenas aquele campo para todo o arquivo ou marcar e preparar cada saída linha para o próximo arquivo de entrada para que o segundo sed possa substituir os campos em questão.

Basicamente funciona com pares de arquivos - a partir do primeiro de cada dois arquivos de leitura, ele imprimirá apenas sua coluna de origem e, em seguida, editará essa coluna de origem no segundo de cada par.

    
por 28.10.2015 / 13:07