Manipulação complicada de texto com o awk

2

Eu tenho um texto pesado com um padrão como abaixo

começa com

------------------
MOLECULAR ORBITALS
------------------
                      0         1         2         3         4         5   
                 -238.19873 -238.19679 -238.16140 -238.16079 -145.83297 -27.39277
                   1.00000   1.00000   1.00000   1.00000   1.00000   1.00000
                  --------  --------  --------  --------  --------  --------
  0C   1s        -0.000000 -0.000000 -0.000000 -0.000000  0.000000 -0.000001
  0C   2s         0.000000  0.000000  0.000000  0.000001 -0.000002  0.000025
  0C   3s         0.000003 -0.000001  0.000005 -0.000002 -0.000020  0.000230
   .
   .
   .
  1C   1px        0.000000  0.000000  0.000000 -0.000000 -0.000000  0.000005
  1C   1py        0.000000  0.000000 -0.000000 -0.000000  0.000000  0.000003
  1C   2pz       -0.000000 -0.000000 -0.000000  0.000000 -0.000005  0.000002
   .
   .
   .
 13Mn  1dyz      -0.000000 -0.000000 -0.000000  0.000000 -0.000000 -0.000006
 13Mn  1dx2y2    -0.000000  0.000000  0.000000 -0.000000 -0.000000 -0.000005
 13Mn  1dxy       0.000000 -0.000000 -0.000000 -0.000000 -0.000000  0.000001
 13Mn  2dz2       0.000000  0.000001  0.000000 -0.000000 -0.000001  0.000008
   .
   .
   .
181H   1pz       -0.000000  0.000000 -0.000000 -0.000000  0.000003 -0.000020
181H   1px       -0.000001  0.000000 -0.000000 -0.000000  0.000003 -0.000103
181H   1py        0.000000 -0.000000 -0.000000 -0.000000 -0.000001  0.000013
                      6         7         8         9        10        11   
                 -27.39007 -27.35069 -27.34994 -23.19934 -23.19836 -23.19760
                   1.00000   1.00000   1.00000   1.00000   1.00000   1.00000
                  --------  --------  --------  --------  --------  --------
  0C   1s         0.000000  0.000001  0.000008  0.000001 -0.000003  0.000001
  0C   2s        -0.000003 -0.000038 -0.000147 -0.000013  0.000059 -0.000019
  0C   3s         0.000087 -0.000445 -0.000002  0.000091  0.000201 -0.000215

Esta é uma prévia do ... apenas significa que continua. Aqui está o arquivo real. (é grande) Eu posso encontrar esses padrões usando o awk

awk '
/MOLECULAR ORBITALS/ {F=1}

F &&
/^[0-9][A-Z]/ {print}' test.out

agora quero somar as linhas sempre que $ 1 = $ 1 (da próxima linha) e a parte alfabética dos $ 2 é igual à parte alfabética de $ 2 por exemplo, as primeiras três linhas devem se parecer com:

0C   1s         0.000003 -0.000001  0.000005 -0.000001  -0.000022  0.000254

Tudo o que posso pensar são arrays no momento, alguém pode sugerir uma solução? Eu estava pensando em usar get line verificando os critérios e somar os valores se os critérios forem iguais. Mas isso não parece limpo. Esse é o jeito certo de fazer isso?

    
por Raymond Ghaffarian Shirazi 29.10.2015 / 18:34

1 resposta

2

Veja um script awk :

awk '
function show(){
  if(lastkey=="")return
  printf "%-10s ",lastkey
  for(i=3;i<=NF;i++)printf "%9f ",values[i]
  printf "\n"
}

/MOLECULAR ORBITALS/ {F=1}
F && ~/[0-9]+[A-Z]+/ { 
 key = ; subkey=; gsub(/[^a-z]/,"",subkey);
 newkey = key " " subkey;
 if(lastkey == newkey)
   for(i=3;i<=NF;i++)values[i] += $i
 else{
  show();
  lastkey = newkey;
  for(i=3;i<=NF;i++)values[i] = $i
 }
}
END{ show(); }
' test.out

A função show() no início é permitir que o último conjunto de valores a serem impressos em eof sem duplicar o código. O gsub() remove os dígitos do segundo campo ($ 2). newkey é então a concatenação do 1º campo com isso, para testar nas linhas posteriores para similaridade. Quando as linhas são semelhantes, os campos 3 até o final (número de campos NF) são adicionados aos valores anteriores, senão eles são impressos e zerados.

    
por meuh 29.10.2015 / 19:57