使用 awk 进行复杂的文本操作

使用 awk 进行复杂的文本操作

我有一篇很重的文字,其图案如下

它始于

------------------
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

这是一个预览...只是意味着它会继续。这里是实际的文件。(它很大)我可以使用 awk 找到这个模式

awk '
/MOLECULAR ORBITALS/ {F=1}

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

现在我想要对当 $1=$1(下一行)并且 $2 的字母部分等于 $2 的字母部分时所对应的行进行求和,例如前三行应该是这样的:

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

我现在唯一能想到的就是数组,有人能提出解决方案吗?我考虑使用 get line 检查条件,如果条件匹配,则将值相加。但这听起来不太清楚。这是正确的做法吗?

答案1

这是一个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 && $1~/[0-9]+[A-Z]+/ { 
 key = $1; subkey=$2; 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

开头的功能show()是允许在 eof 处打印最后一组值而不重复代码。gsub()删除第二个字段 ($2) 中的数字。newkey 是第一个字段与此字段的串联,用于测试后面的行是否相似。当行相似时,将字段 3 到末尾(NF 个字段)添加到前面的值中,否则将它们打印并清零。

相关内容