Encontre e substitua colunas diferentes usando o awk

3

Eu tento fazer uma alteração em um arquivo:

Encontre um determinado valor e substitua-o por outro valor em uma coluna diferente usando awk .

Entrada ( UiO-66Zr-EH.mof ):

unit ntype qqatom
  1  'Zr1'  0.0d0
vibration
0
improper
0
unit ntype qqatom
  2  'H1'  0.0d0
vibration
0
improper
0
unit ntype qqatom
  3  'C25'  0.0d0
vibration
0
improper
0
unit ntype qqatom
  4  'O1'  0.0d0

Saída ( output ):

unit ntype qqatom
  1  'Zr1'  2.222d0
vibration
0
improper
0
unit ntype qqatom
  2  'H1'  3.333d0
vibration
0
improper
0
unit ntype qqatom
  3  'C25'  7.456d0
vibration
0
improper
0
unit ntype qqatom
  4  'O1'  9.99d0

Eu tentei este comando:

awk < UiO-66Zr-EH.mof '$2 ~ /Zr1/ {$3 ="2.222.d0"}1''$2 ~ /O1/ {$3 ="9.99d0"}1''$2 ~ /C25/ {$3 ="7.45d0"}1''$2 ~ /H1/ {$3 ="3.333d0"}1' > output

Mas isso não funcionou muito bem.

Posso fazer isso com awk , mantendo a mesma formação?

    
por Joao Macau 01.07.2014 / 17:08

2 respostas

2

Em vez de fazer uma correspondência de expressão regular na segunda coluna, você provavelmente deseja apenas uma comparação de sequência de caracteres. Para fazer isso com o exemplo que você deu, você tem que incluir as aspas simples na comparação que transforma a coisa toda em um pesadelo de citação de shell. Isso faz o seguinte:

awk "\==\"'Zr1'\" { \=\"2.222.d0\" }
     \==\"'O1'\" { \=\"9.99d0\" }
     \==\"'C25'\" { \ =\"7.45d0\" }
     \==\"'H1'\" { \ =\"3.333d0\" }
     { print }" <UiO-66Zr-EH.mof
    
por 01.07.2014 / 18:25
2

A primeira questão aqui é que seus valores são citados. Sugiro que você simplesmente remova as aspas com o comando sed e, se realmente precisar delas, coloque-as de volta depois de processar o arquivo com awk . Algo como

sed "s/'//g" UiO-66Zr-EH.mof | awk '{$2=q $2 q}' q="'" 

O truque acima define a variável q to ' então q $2 q é equivalente a '$2' . Apenas uma maneira fácil de fazer com que awk seja legal com aspas simples.

Com base no seu script, você parece querer realizar as seguintes substituições:

$2 is   $3 should be
---------------------
Zr1     2.008.d0
O25     -1.179d0
O1      -0.582d0
C25     -0.121d0
C13     -0.002d0
C1      0.625d0
O29     -0.741d0
H1      0.127d0
H25     0.495d0

Se assim for, eu faria algo como

$ sed "s/'//g" UiO-66Zr-EH.mof |
   awk 'BEGIN{
        c["Zr1"] = "2.008.d0";
        c["O25"] = "-1.179d0";
        c["O1"] = "-0.582d0";
        c["C25"] = "-0.121d0";
        c["C13"] = "-0.002d0";
        c["C1"] = "0.625d0";
        c["O29"] = "-0.741d0";
        c["H1"] = "0.127d0";
        c["H25"] = "0.495d0";
        }
    {if( $2 in c){$3=c[$2]; $2=q$2q}}1;' q="'" 

Explicação

  • O sed inicial apenas remove todas as aspas simples do arquivo de entrada.
  • O resultado do sed é passado como entrada para awk
  • O bloco BEGIN{} é executado antes de o arquivo ser lido e um conjunto associativo contendo seus mapeamentos está configurado.
  • No programa principal, simplesmente verifico se $2 está definido na matriz c e, se estiver, substituirei $3 pelo valor correspondente da matriz.
  • O $2=q$2q apenas coloca as aspas simples em torno de $2 .
  • Finalmente, o 1; imprime a linha.

A saída quando executada no seu exemplo é:

unit ntype qqatom
1 'Zr1' 2.008.d0
vibration
0
improper
0
unit ntype qqatom
2 'H1' 0.127d0
vibration
0
improper
0
unit ntype qqatom
3 'C25' -0.121d0
vibration
0
improper
0
unit ntype qqatom
4 'O1' -0.582d0
    
por 01.07.2014 / 18:43