我有一篇很重的文字,其图案如下
它始于
------------------
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 个字段)添加到前面的值中,否则将它们打印并清零。