Операции с текстовым файлом табличных данных с использованием awk

Я создаю длинный табличный текстовый файл, извлекая информацию из набора файлов журнала. Я хотел сделать некоторые операции с полученными табличными данными и создать новый текстовый файл с табличными данными.

Мои табличные данные выглядят так

Compound    State       Method      Approach    Energy
C(CCH)2         singlet     CC          Triplet orbs    not converged or error  3-1/C-CCH-2/C-CCH-2-CC-s.out
C(CCH)2         singlet     CC          Triplet orbs    -191.426232325854   3-1/C-CCH-2/C-CCH-2-s.out
C(CCH)2         triplet     CC          Triplet orbs    -191.434509836762   3-1/C-CCH-2/C-CCH-2-t.out
C(NH2)2         triplet     DFT         Triplet orbs    not converged or error  3-1/C-NH2-2/C-NH2-2-t.out
C(NMe2)2        triplet     DFT         Triplet orbs    not converged or error  3-1/C-NMe2-2/C-NMe2-2-t.out
C(SH)2          singlet     CC          Triplet orbs    not converged or error  3-1/C-SH-2/C-SH-2-CC-s.out
C(SH)2          singlet     DFT         Triplet orbs    -835.261598037781   3-1/C-SH-2/C-SH-2-s.out
C(SH)2          triplet     DFT         Triplet orbs    -835.190581480918   3-1/C-SH-2/C-SH-2-t.out
C(SiH3)2        singlet     CC          Triplet orbs    not converged or error  3-1/C-SiH3-2/C-SiH3-2-CC-s.out
C(SiH3)2        singlet     DFT         Triplet orbs    -620.339326760127   3-1/C-SiH3-2/C-SiH3-2-s.out
C(SiH3)2        triplet     DFT         Triplet orbs    -620.379515709604   3-1/C-SiH3-2/C-SiH3-2-t.out
CF2             singlet     CC          Triplet orbs    not converged or error  3-1/CF2/CF2-CC-s.out
CF2             singlet     DFT         Triplet orbs    -237.686609290184   3-1/CF2/CF2-s.out
CF2             triplet     DFT         Triplet orbs    -237.601091999318   3-1/CF2/CF2-t.out
CF2C            singlet     CC          Triplet orbs    not converged or error  3-1/CF2C/CF2C-CC-s.out
CF2C            singlet     DFT         Triplet orbs    -275.668206445318   3-1/CF2C/CF2C-s.out
CF2C            triplet     DFT         Triplet orbs    -275.641632193745   3-1/CF2C/CF2C-t.out
CH2             singlet     CC          Triplet orbs    -39.061384267881    3-1/CH2/CH2-CC-s.out
CH2             singlet     DFT         Triplet orbs    -39.109884610315    3-1/CH2/CH2-s.out
CH2             triplet     DFT         Triplet orbs    -39.129586138474    3-1/CH2/CH2-t.out

и код, производящий его, выглядит следующим образом:

awk '
BEGIN           {print "Compound\tState\t\tMethod\t\tApproach\tEnergy"}'
find . -name '*.out' | while read FILENAME

do

awk '
FNR==1          {if (FILENAME ~ /-/) 
                  { sub("./","", FILENAME);m=split(FILENAME, Ti, "/") 
                             n=split(Ti[m], T, "-")
                             if (length(T[1]) < 2 ) {T[1]=T[1]"("T[2]")"substr(T[3],1,1)}
                             printf("%-15.10s\t%-10s\t%-10s\t%-10s\t",  T[1], substr(T[n],1,1)=="t"?"triplet":"singlet", FILENAME~"-CC"?"CC":"DFT",FILENAME~"3-1"?"Triplet orbs":"NONE");
                             FOUND=0
                 }
                 else
                  {sub("./","", FILENAME);m=split(FILENAME, Ti, "/") 
                             n=split(Ti[m], T, ".")
                             if (length(T[1]) < 2 ) {T[1]=T[1]"("T[2]")"T[3]}
                             printf ("%-15.10s\t%-10s\t%-10s\t%-10s\t", T[1] , "Singlet", "DFT",FILENAME~"3-1"?"Triplet orbs":"NONE");
                             FOUND=0
                }
                }
/HURRAY/        {FOUND=1; 
                }
FOUND &&
/^FINAL.*ERGY/  {print $NF " \t" FILENAME 
                 CONV=1
                }
END             {if (!CONV) print "not converged or error\t" FILENAME 
                };       
' OFS="\t" "$FILENAME"
done 

Я хотел, чтобы всякий раз, когда столбцы: Соединение, Метод и Подход соответствуют значениям энергии, они были уменьшены друг от друга точно так же, как синглет-триплет, и все вместе формировали новые табличные данные. Например

CF2             singlet     DFT         Triplet orbs    -237.686609290184   3-1/CF2/CF2-s.out
CF2             triplet     DFT         Triplet orbs    -237.601091999318   3-1/CF2/CF2-t.out

Сформируйте один ряд как

CF2             DFT         Triplet orbs    0.085517290866  

и, конечно, если совпадение не найдено, просто ошибка не найдена или данные недоступны. Ваша помощь приветствуется.


person Raymond gsh    schedule 24.08.2015    source источник


Ответы (1)


Я не пытался читать ваш awk-скрипт, но предположил, что вы начинаете с данных, перечисленных выше.

awk -vOFS="\t" -f m.awk data

будет генерировать

C(CCH)2     CC      Triplet orbs    -0.00827751
C(SH)2      DFT     Triplet orbs    0.0710166
C(SiH3)2    DFT     Triplet orbs    -0.0401889
CF2 DFT     Triplet orbs    0.0855173
CF2C        DFT     Triplet orbs    0.0265743
CH2 DFT     Triplet orbs    -0.0197015

вот сценарий

 $ cat m.awk
    {
      k = $1 OFS $3 OFS $4
    }
    $2 ~ /singlet/  {
      if ($6 = $6 + 0) {
        if (k in t) {
          print k, $5, t[k] - $6
          t[k] = ""
        } else {
          s[k] = $6
        }
      }
    }

    $2 ~ /triplet/  {
      if ($6 = $6 + 0) {
        if (k in s) {
          print k, $5, $6 - s[k]
          s[k] = ""
        } else {
          t[k] = $6
        }
      }
    }

Объяснение: составить ключ из полей 1,3,4. Попробуйте сопоставить одиночные и тройные пары, когда значение является числом. Когда используется пара, аннулируйте используемое значение.

Мы можем извлечь общую логику в функцию, чтобы еще больше упростить код.

  function pairup(t,s,sign) {
    if ($6 = $6 + 0) {
      if (k in t) {
        print k, $5, sign*(t[k] - $6)
        delete t[k]
      } else {
        s[k] = $6
      }
    }
  }

 {k = $1 OFS $3 OFS $4}

 $2 ~ /singlet/{pairup(t,s,1)}

 $2 ~ /triplet/{pairup(s,t,-1)}

Я думаю, вы можете еще больше упростить, сократив использование одного массива, но у вас нет времени работать над этим.

person karakfa    schedule 24.08.2015
comment
извините за нуб, последняя часть дает мне: k: команда не найдена, это функция awk? это не похоже на баш? - person Raymond gsh; 25.08.2015